![](https://secure.gravatar.com/avatar/33723e8059722928b8dfe2921435f9de.jpg?s=120&d=mm&r=g)
impromptu is a live-coding environment for OS X that looks very interesting, definitely something I need to try out once I've escaped the clutches of my end-of-year work. http://impromptu.moso.com.au/ I thought I'd bring it up not only because it's interesting, but because its tutorial on "time" contrasts impromptu's asynchronous model with ChucK's synchronous one: in impromptu, time passes while your code is running. You can read the tutorial here: http://impromptu.moso.com.au/tutorials/time.html Just think... you could load a WAV file without hanging the VM! It's interesting to see what you get when you trade one complication (waiting on slow shreds) for another (having "now" change beneath your feet). Here are some, from the tutorial: "There are a couple of gotcha's to keep in mind when doing schedule and forget programming. The first thing to keep in mind is that (now) is an airy fairy thing. In the example below the two notes may be scheduled to play on the same sample - but then again, they may not - (now) may have moved forward in time between the two calls (even if evaluated at the same time). (play-note (now) piano 60 80 *second*) (play-note (now) piano 72 80 *second*) "Often this lack of precision is fine (i.e. too small a change to be noticeable) but where absolute accuracy is required a time variable should be used. (let ((time (now))) (play-note time piano 60 80 *second*) (play-note time piano 72 80 *second*)) "This inaccuracy becomes more of an issue when amplified over time such as using (now) inside a recursive callback loop. We can avoid the problem by precisely incrementing a time value between each recursive callback (note that any arguments required by the function being called back must also be passed to callback). ;This is bad (define loop (lambda () (play-note (now) piano 60 80 *second*) (callback (+ (now) *second*) 'loop))) (loop) ;This is good (precise time arg is now incremented each recursion) (define loop (lambda (time) (play-note time piano 60 80 *second* ) (callback (+ time *second*) 'loop (+ time *second*)))) (loop (now)) "The second major gotcha in recursive callback loops is that (now) is now. Code requires some time to execute. If you are executing a call to evaluate a note (now) by the time the code is evaluated it will already be late. You should always try to schedule your code execution ahead of the scheduled time of your tasks. ;This is best (callback happens 4100 samples earlier than new time) (define loop (lambda (time) (play-note time piano 60 80 1.0) (callback (+ time 40000) 'loop (+ time 44100)))) (loop (now)) "In the this-is-good version of loop the time sent as an argument to loop is exactly the same time as the scheduled callback time. The problem with this is that the next note needs to be scheduled at exactly the same time that the function is called. The note will always be late. The this-is-best version schedules the callback just ahead of the time that we want to schedule the note. This gives us 4100 samples to execute the code to schedule the note before the note is required to sound." The last sentence reminds me of the thread a while back about benchmarking UGens. :) -- Tom Lieber http://AllTom.com/