Slub have a number of important livecoding transmissions coming up (including a performance at the Mozilla Festival!) so it’s time to work on fluxus/fluxa/scheme bricks. Here are some recording tests of a feature I’ve been wanting to use for a long time – temporal recursion.
These recordings were not changed by hand as they played, but started and left running in ‘generative audio’ mode in order to try and understand the technique. This method of sequencing is inspired by Impromptu which uses a similar idea. In fluxa it’s all based around a single new function: “in” which schedules a call to a function – which can be the current function (this is different to the existing ‘timed tasks’ in fluxus which are less precise for this kind of sequencing).
(define (tick time a) (play (+ time 3) (sample "ga.wav" (note (pick '(40 42 45) a)))) (in time 0.22 tick (+ a 1))) (in (time-now) 1 tick 0)
The “in” function takes the current time, the time to wait before the call, the function to call and it’s parameters. In the example above the argument “a” gets incremented each time, resulting in a sequence of notes being played. Recursion generally brings up thoughts of self similarity and fractal patterns – as in the graphical use of recursion in fluxus, but here it’s better to imagine a graph of function calls. Each function can branch to a arbitrary number of others, so limitations have to be put in place to stop the thing exploding with too many concurrent calls. What seems to happen (even with small function call graphs) is the appearance of high level time structures – state changes and shifts into different modes where different patterns of calls lock into sequence. You can hear this clearly in the second recording above which alters itself half way through.
I’ve also experimented with visualising the call graph, with limited success with this more complex example – the round nodes are functions, the boxes parameter changes and labels on the connections are the branch conditions:
(require fluxus-018/fluxa) (searchpath "/home/dave/noiz/nm/") (define n '(23 30)) (set-scale '(1 1 2 1)) (define (za time a b) (play (+ time 3) (mul (mul (adsr 0 0.1 1 1) (pick '(0.4 0.1 1 0.4 1) a)) (sample "ga.wav" (note (- (modulo (- b a) 17) (* (pick n a) 2))))) -0.5) (when (zero? (modulo a 16)) (in time 0.3 zm a b)) (if (eq? (modulo a 14) 12) (in time 1.0 zoom a (- b 1)) (in time (- 0.5 (* (modulo a 13) 0.03)) za (+ a 1) (+ b 2)))) (define (zm time a b) (play (+ time 3) (mul (mul (adsr 0 0.1 1 1) (pick '(0.1 0.4 1) a)) (sample "ga.wav" (note (+ (modulo b 5) (/ (pick n a) 2))))) 0.5) (if (> a 12) (in time 1.0 za b a) (in time (pick '(1.3 1.5 0.5) a) zm (+ a 1) b))) (define (zoom time a b) (play (+ time 3) (mul (mul (adsr 0 0.1 1 1) (pick '(0.1 0.2 0.3) a)) (sample "ga.wav" (note (+ (pick n a) (* 3 (modulo a (+ 1 (modulo b 5))))))))) (if (> a 16) (in time 0.3 zm 0 (+ b 1)) (in time (pick '(1.3 0.12) a) zoom (+ a 1) b))) (in (time-now) 1 zoom 0 1)