Search code examples
audiosupercollider

How to programmatically stop sound playback in SuperCollider


I have the following piece of code, which should play a synth function for one second, stop it, play it again after one second, and so on:

    t = Task({{
    var a;
    a =  {[0,0,SinOsc.ar(852, 0, 2.2)+SinOsc.ar(1633, 0, 2.2), 0]} ;
    a.play;
    1.wait;
    a.release(5);
    1.wait;
   }.loop});

   t.play;

The problem is, a doesn't stop playing, but additional a's get started on the server. What is wrong here, how can a playing synth be stopped?


Solution

  • In that code, a is a function, so a.release does not tell the synth to stop playing.

    Instead, why not write a SynthDef with a 5 second long envelope on it:

    SynthDef(\sines, {arg out = 0, release_dur, gate =1, amp = 0.2;
        var sines, env;
        env = EnvGen.kr(Env.asr(0.01, amp, release_dur), gate, doneAction:2);
        sines = SinOsc.ar(852, 0, 2.2)+SinOsc.ar(1633, 0, 2.2);
        Out.ar(out, sines * env);
    }).add
    
    t = Task({{
        var a;
        a =  Synth.new(\sines, [\release_dur, 5, \out, 0, \amp, 0.2, \gate, 1]);
        1.wait;
        a.set(\gate, 0);
        1.wait;
       }.loop});
    
       t.play;
    

    We'll pass in the release duration as an argument, so you can set it in the task below in the a =Synth line.

    Then, when you want to end the synth, send it gate of 0. this tells the envelope to release, which it does over 5 seconds, then the doneAction removes the synth from the server. Note that you will have more than one synth playing at once, because the release time is longer than your wait time.

    Also, you've set the amplitude for your sines to be greater than 1. I did not change this in the synthdef above.