Search code examples
supercollider

How to wait within array iteration?


[1,2,3].do { /* how to wait 1s here? */ }

I am learning supercollider. I have found the SimpleNumber.wait function, but I soon learned that it doesn't work within "normal" functions, only within some "different" kind of functions called Routines.

I deliberately stopped right there to ask the question: is there a simple way to pause for a given amount of time within each iteration of the someArray.do construct? By "simple way" I mean something that won't require learning a dozen new concepts and going through a paradigm shift.

NOTE WELL: I know that I will eventually need to learn the whole huge book about Routines, Tasks and other sequencing mechanisms in supercollider, but for now I just want to play "Mary Had A Little Lamb" and call it a noob's day, without having to learn all of that before I can make anything at all happen.

Is this possible?


Solution

  • A Routine is required to use .wait / .yield functionality. When you call e.g. 3.wait, you're telling a Clock somewhere to wait for 3 seconds, and then continue things from where you left off. In order to do this, you need to be communicating with a clock, and you need something that can be stopped and started (a Routine executing some function).

    The complete syntax for what you're trying to do would be:

    Routine({
       [1, 2, 3].do {
          |n|
          n.postln;
          1.wait;
       }
    }).play(AppClock);
    

    The above creates a Routine with a function (your 1, 2, 3 loop), and then plays it on a clock (AppClock, the standard clock).

    However, the .fork method on functions is a shorthand for doing the above (i.e. creating a Routine and playing it):

    {
       [1, 2, 3].do {
          |n|
          n.postln;
          1.wait;
       }
    }.fork();