Playing a Pattern Only While Holding a MIDI Note?

I have some code I am working on that takes a collection of held notes and plays a randomized version. The code sends out MIDI data to my DAW to trigger some Kontakt instruments. Right now I have it working largely how I want it, but I am having trouble working out how to get things to stop when I want them to.

I have a MIDIFunc.noteOn playing a Pseq of a couple of Pbindefs (that was the only way I could get it to send a cc message to change articulations, and then send a note. For example:

Pbindef(\violinOneArticulation,

\type, \midi,

\midiout, m,

\midicmd, \control,

\chan, 0,

\control, 20,

\ctlNum, 32,

\dur, Pseq([0.1], 1),

);

Pbindef(\violinOneNote,

\type, \midi,

\midicmd, \noteOn,

\midiout, m,

\chan, 0,

\midinote, Pfuncn({ ~violinOneHeld.choose }, 1),

\dur, Pwhite(0.25, Pfunc({ ~violinOneDuration })),

);

I have these Pbindefs triggered by a couple of MIDIFuncs (as well as one to clear the array of notes)

MIDIFunc.noteOn({ |vel, num, chan, src|

Pseq([

Pbindef(\violinOneArticulation, control: Prand([20,31,43], 3)),

Pbindef(\violinOneNote)

], 4).play; }, 120, 0);

MIDIFunc.noteOn({ |vel, num, chan, src|

Pseq([

Pbindef(\violinOneArticulation, control: Prand([8,10,21,18], 3)),

Pbindef(\violinOneNote)

], 4).play; }, 119, 0);

MIDIFunc.noteOff({ |vel, num, chan, src|

~violinOneHeld.clear;

}, 118, 0);

Right now, the 4s in the noteOn repeats are just a placeholder. What I would like to do is have the randomized noted continue to playback until the trigger note, like 120 or so, is released. I am still fairly new to SuperCollider, so I cannot figure it out.

Thank you!

Hi, welcome!

Pdef and Pbindef include their own storage, so you can play and stop them directly. But when you play Pbind or Pseq directly, then there’s an additional object to manage: an EventStreamPlayer. This is created by .play, and to stop it, you need to first save it in a variable, then call .stop on the variable.

MIDIFunc.noteOn({ |vel, num, chan, src|
    if(~note120.isNil) {
        ~note120 = Pseq([
            ... your stuff here
        ], 4).play;
    };
}, 120, 0);

Then a MIDIFunc.noteOff would do ~note120.stop; ~note120 = nil;.

Or use Pdef to wrap the Pseq objects (where Pdef provides the same kind of built in storage as Pbindef).

hjh

Thank you so much! I couldn’t get the variable approach to work the way I wanted, but wrapping everything in a Pdef did! I very much appreciate it!