[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[sc-users] Playbuf Done Actions / Triggering Samples and PlayBufs



Dear List, 


I've been looking for a solution to this for a while but I've been struggling with this. I wonder if anyone has had a similar problem or knows a solution. 


All I want to do is to trigger samples: when one ends, another one starts. I don't want any looping; I just want to create a long chain of samples that get triggered by the one that came before it. Before I started using Supercollider I thought that this might be possible with the kind of 'End of Cycle' gate outputs you get on some envelope generators, such as Make Noise's Maths; the idea being that once an envelope closes it sends a gate out to another envelope, triggering the new sample. 


Here are some of the things I've looked at:

  • PlayBuf has done actions but all the done actions seem to be to do with freeing synths. 
  • You can use a Line.kr with a Done.kr to 'time' when something ends, and then send a trigger to another synth. I've seen this work perfectly with generic synths, but not with PlayBufs. Using Line/Done.kr could be a solution. An simple example of this can be found in the Done U-gen help file:
(
SynthDef("Done-help", { arg out, t_trig;
    var line, a, b;

    line= Line.kr(1,0,1);

    a= SinOsc.ar(440,0,0.1*line); //sound fading out
    b= WhiteNoise.ar(Done.kr(line)*0.1); //noise starts at end of line

    Out.ar(out, Pan2.ar(a+b));
}).add;
)

  • I tried to implement the above with PlayBufs. In my code, I tried to add a new variable which is essentially {sample}.duration, and then to use that variable in a Line.kr's length. I wanted to emulate what is going on in the example above but with this new 'duration' variable. The problem is, in the above example, the Done.kr*0.1 is acting on the WhiteNoise.ar's 'mul' argument, which just increases its volume. How can we get that Done.kr to say, send a message to a second Impulse.kr, which is placed in the second PlayBuf? I tried to demonstrate my ideas below, but it doesn't work. There might be something fundamentally wrong with my approach.
  • ~_one_ = Buffer.read(s, "/Users/xxx.wav");

    ~two = Buffer.read(s, "/Users/xxxx.wav");

    (
    SynthDef(\Sample, {out;
     var line, a, b, trig2;

     line = Line.kr(1,0,dur:~one.duration);
     done = Done.kr(line);
     done.postln;
     trig2 = Impulse.ar(done*0.1);

     a = PlayBuf.ar(1, ~one, rate:1, trigger:Impulse.ar(0));
     b = PlayBuf.ar(1, ~two, rate:1, trigger:trig2);
     
     Out.ar(out, Pan2.ar(a+b));
    }.add;

    ))


  • OSCresponder: I saw some posts that people had written by some guy who was having same problem with me, but he was writing 8 years ago, and when I check about OSCresponder it's apparently 'out of date' now, everyone should use OSCFunc. Using OSC messages within a Supercollider patch seems like it could be an efficient method, and it would certainly be easy to 'read' the code and define the address messages. Is it possible to get a PlayBuf to send an OSC message to the server, which can then be read by another PlayBuf to trigger it? Below is an example of the type of code I'm talking about.

(

// calling the language when receiving a trigger:

SynthDef("detector", { arg thresh=0.05;

var trig;

trig = SoundIn.ar(0); // reading from the first audio input of the interface  

trig = Amplitude.ar(trig, 0.002, 0.02) > thresh;

SendTrig.ar(trig,0,trig);

}).send(s);

)


(

// register to receive this message

OSCresponder(s.addr,'/tr',{ arg time,responder,msg;

"something happened!\n".postln;

}).add;

)



y = Synth("detector");


y.free;



(

// a responder which generates and plays a new SynthDef on every 'tr' message

OSCresponder(s.addr,'/tr',{ arg time,responder,msg;

{ SinOsc.ar(rrand(300, 500), 0, XLine.kr(0.5, 0.01, 0.1, doneAction: 2)) }.play;

}).add;

)


y = Synth("detector");


y.free;



Thanks for taking the time to read if you've gotten this far!


Regards,

Joe