Pull-off effect on MIDI keyboard

I’m fairly new to both synthesis and SuperCollider.

I’m trying to get SuperCollider, Arturia MicroBrute & KeyStep, Akai MIDIMix and Native Instruments Komplete Audio 6 MkII working together in various ways. I’ve managed to use the MIDIMix with the Modality toolkit to control some SuperCollider synths.

I’m currently trying to develop a synth that will output some oscillators to the 'brute that will be mixed and fine tuned on the MIDIMix. I’ve got it sending just a SinOsc to the 'brute at the moment and its working for the most part.

The thing I’d like to figure at the moment is this. On the 'brute when i hold a key and keep holding it while I’ve hit another when i let go of the second key it does something like a guitar pull-off back to the first note. I actually really like this effect coming from a guitar background… it lets me bang out some really cool stoner rock sludge type stuff amongst other things. But my SinOsc does not do this.

(
SynthDef("brutesine", { |out = 1, freq, gate = 0.0|
    var x;
    x = SinOsc.ar(freq);
    x = EnvGen.kr(Env.adsr, gate, Latch.kr(gate, gate)) * x;
    Out.ar(out, x);
}).add;
)

x = Synth("brutesine");

(
MIDIClient.init;
MIDIIn.connect(0, 2097152); // Connect to KeyStep
MIDIIn.connect(0, 1835008); // Connect to MicroBrute
)

(
~noteOn = {arg src, chan, num;
    x.set(\freq, num.midicps);
    x.set(\gate, 1);
};
MIDIIn.addFuncTo(\noteOn, ~noteOn);
~noteOff = { arg src,chan,num,vel;
    x.set(\gate, 0);
};
MIDIIn.addFuncTo(\noteOff, ~noteOff);
)

You’ll need to keep an array, in order, of note-on messages.

  • Note on: Add the note number to the end of the array, and change the oscillator frequency.

  • Note off: Find the index of the note number in the array (indexOf).

    • Delete the note number from the array (array.removeAt(index)).
    • If the note being released is the last in the array (index == array.size – that’s old index vs new array size), then change the oscillator frequency to array.last (or, if there aren’t any more notes, release the synth).

hjh

One suggestion: MIDIFunc or MIDIdef, not MIDIIn.

“For most uses, the preferred way to receive MIDI input is using the MIDIFunc and MIDIdef classes.” – http://doc.sccode.org/Guides/UsingMIDI.html

MIDIClient.init;
MIDIIn.connectAll;

(
var activeNotes = Array.new;
var synth;

MIDIdef.noteOn(\on, { |velocity, num|
	if(activeNotes.isEmpty) {
		synth = Synth(\default, [freq: num.midicps, amp: 0.2]);
	} {
		synth.set(\freq, num.midicps);
	};
	activeNotes = activeNotes.add(num);
});

MIDIdef.noteOff(\off, { |velocity, num|
	var index = activeNotes.indexOf(num);
	if(index.isNil) {
		"Note off % without corresponding note on".format(num).warn;
	} {
		activeNotes.removeAt(index);
		if(activeNotes.isEmpty) {
			synth.release;  // no more notes, so release
			synth = nil;
		} {
			if(index == activeNotes.size) {
				synth.set(\freq, activeNotes.last.midicps);
			};
		};
	};
});
)

Also, from your code:

x = EnvGen.kr(Env.adsr, gate, Latch.kr(gate, gate)) * x;

Don’t forget:

x = EnvGen.kr(Env.adsr, gate, Latch.kr(gate, gate), doneAction: 2) * x;

hjh

Thanks for your reply. Your code works with \default but its not tying in with my \brutesine for some reason. I’m trying to figure out what’s going on but I’m realizing I stepped into the deep end (I’m not the far into learning SuperCollider but was trying to get my hardware working with it despite) . I was using MIDIIn because I was able to get the code on its help file working for me. I had a go at the example on the ‘Using MIDI’ help file (which uses MIDIFunc) as well, I don’t remember what happened exactly but I think it had to do with stripping out the velocity stuff as I don’t want it for this.

And a few minutes later I got it. I had to tie in the gate. Thanks.

Ah, ok, I missed that. It’s generally recommended to set a nonzero default for gate (SynthDef(\name, { |out = 0, gate = 1, etc...| ... }).add). \default does this but I guess yours didn’t.

MIDIFunc/def do pass velocity first, but my code illustrates how to ignore it.

hjh