[CM] Using Stalin as a realtime extension language for Snd.

Kjetil S. Matheussen k.s.matheussen at notam02.no
Mon May 26 08:51:07 PDT 2008

Lately I've been working on making the Scheme compiler
"Stalin" work as an extension language for the realtime
system in Snd.

Its still a little bit incomplete, and there are some known
bugs, but its very cool and there's definitly sound now.

Stalin is an almost conforming R4RS Scheme
compiler written by Jeffrey Siskind, and it produces
code which competes with, and is often faster than,
hand-written C. And of course it provides common Scheme
features such as closures, higher order functions,
lists, vectors, continuations and so on.

And since all of this is now available in realtime, this
system should provide the first no-compromise
realtime music programming environment.

Evaluating the following block makes a cloud of 50-60 sinus grains
playing simultaniously, spawning a new grain every 15 ms
on average:

  (let loop ()
    (spawn :wait (irandom 30):-ms
      (define osc (make-oscil :frequency (ibetween 50 2000)))
      (define duration (ibetween 400 2000):-ms)
      (define e (make-env '(0 0 0.5 0.05 1 0) :end duration))
      (block :dur duration :cont #f
        (out (* (env e)
                (oscil osc)))))))


On my four year old machine, this block uses about 50%
cpu time. I think though, that much of that
time is spent in the garbage collector/memory allocator,
and there are some thing which can yet be done to
significantly increase the performance of the garbage
collector and memory allocator.

Note that everyting inside the <rt-stalin> block happens
inside the realtime thread, including the spawning of
new "block" blocks, so scheduling is guaranteed
to both be on time and to be frame accurate. (This can
be done in the language "Chuck" as well, but at about
100 times (I would guess) slower speed. (I have measured
Chuck to be about 40 times slower than the RT compiler
when doing frame by frame processing, so Chuck is
probably about 100 times (or so) slower than Stalin.))

The following block creates a simple polyphonic midi soft synth:

  (let loop ()
    (wait-midi :cont (loop)
      (when (midi-play?)
        (let ((note (midi-note)))

          ;; Spawn a simple oscillator
          (define oscillator (spawn
                               (let ((osc (make-oscil :frequency (midi-to-freq note))))
                                   (out (* 0.2 (oscil osc)))))))

          ;; Spawn a job waiting for a stop message for this note.
            (wait-midi :cont #f
              (when (and (midi-stop?)
                         (= note
                (stop oscillator)
                #t))) ;; Got it. Stop waiting for more midi.

          #t))))) ;; Got it.

I think I'll change the syntax a little bit for midi though.

The code for Snd is in CVS. Required packages are:


Rollendurchmesserzeitsammler: (at least v0.0.3)


(Oh, and I've added coroutines to the old "rt" compiler
  as well, like in Chuck. See the file rt-coroutines.scm)

More information about the Cmdist mailing list