Search code examples
processingsupercollider

SuperCollider - Limiting Synth Instances


Im experimenting with SuperCollider and Processing, essentially just having Processing send messages to SC (play this note, at this time, etc).

However, I'm having trouble understanding one thing with SC: if I make a SynthDef, and lets say I have various MIDI notes coming in from Processing, is it not possible to just have ONE instance of the synth, handle playing all the notes?

Right now, SC is creating a new instance of the Synth for every note, and so inevitably, I get a huge build up of instances. I've been trying Synth( and Synth.new but every circumstance seems to create a new instance per received message.

Code Example:

(
SynthDef('simple', {
    arg pitch = 200, msg = 50;
    var sound = SinOsc.ar(pitch);
    var linen = Env.linen(attackTime: 0, sustainTime:0.1, releaseTime:1);
    var env = EnvGen.kr(linen);
    Out.ar(0, sound * env);
}).add;

)

(
var choices = [50, 52, 54, 55, 57, 59, 61, 62, 64 ,66, 67, 69, 71, 73, 74, 76, 78, 79, 81, 83, 85];

OSCdef('listenerXsmall', {
    arg msg;
    msg.postln;
    Synth('simple', [pitch: choices[msg[1]].midicps])
    }, '/hitXsmall');

)

Essentially, I create a SynthDef, and a listener. Integers are received from Processing, which get mapped to array keys to determine what MIDI note to play. But everytime the listener is triggered, I get a new instance of a Synth


Solution

  • Yes it is possible. You simply have to program it! You have two common design patterns to choose from here:

    1. Every time a '/hitXsmall' is received, you launch a new synth. In this case, you probably want to use doneAction:2 in your EnvGen so that the synth automatically frees itself. See the EnvGen helpfile and the doneActions helpfile for info and examples.

    2. At the start of your code, you launch one single never-ending synth and store a reference to it in a variable, e.g. x = Synth(...). Then, every time a '/hitXsmall' is received, you use the set message to tell the synth new parameters to use, e.g. x.set(\freq, 440, \amp, 0.5).

    In your code example, you've got a synth which is all about creating a single bounded note, so I would recommend the first approach. Use doneAction:2 to make the synths free themselves when done, and all is fine.