;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;

;; EAMPLE USING THREE CITTERS TO CONTROL AUDIO PARAMETERS

;;

;; Define three "critters" to crawl around the window

;; setting x/y coordinates (au parameters) as they

;; go.

;;

;; NOTE: This example uses the Automat AudioUnit but

;; you can replace it with another AU of your choosing

;; as long as you change the parameter choices to

;; something suiteable (and within the appropriate range).

;; Automat is free anad availible from:

;; http://www.alphakanal.de/snipsnap/space/automat

;; 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


; make sure that nothing is already connected

(au:clear-graph)


;; Setup AudioUnit chain

; Locate availible audio unit instruments

; This will list those installed on your machine in the log window.

(au:print-audiounits "aumu")

(au:print-audiounits "aufx")

; choose some units to work with

(define automat (au:make-node "aumu" "auto" "Alfa"))

(define delay (au:make-node "aufx" "dely" "appl"))

(define reverb (au:make-node "aufx" "mrev" "appl"))

(au:connect-node reverb 0 *au:output-node* 0)

(au:connect-node delay 0 reverb 0)

(au:connect-node automat 0 delay 0)

(au:update-graph)


;; Show the visual interface for the synth

(au:open-view automat)


;; Set some init params for the audio units

; Most audio units have ajustable parameters. They can

; be altered from Impromptu programatically. or via

; their visual interface which is exposed using au:open-view.

; The au:print-param-names function will list in the

; log window the parameters for the specified audio unit.

(au:print-params automat *au:global-scope*)

(au:set-param (now) automat 11 0 0 4) ; waveform

(au:set-param (now) automat 56 0 0 1) ; filter type

(au:set-param (now) automat 70 0 0 0.5) ; filter resonance

(au:set-param (now) automat 59 0 0 0.5) ; filter envelope

(au:set-param (now) automat 69 0 0 0.3) ; filter cutoff

(au:set-param (now) automat 36 0 0 0.0) ; osc 2 vol

(au:set-param (now) automat 51 0 0 0.0) ; osc 3 vol

(au:set-param (now) automat 14 0 0 0.0) ; osc 3 vol


(au:print-params reverb *au:global-scope*)

(au:set-param (now) reverb 0 0 0 30) ; wet/dry mix

; (au:set-param (now) reverb 1 0 0 20)


;; test?

; (play-note (now) automat 60 80 *second*)

           

(define *critter-canvas* (gfx:make-canvas))

(define *go* #t)


;; Function to move shape randomly within the Window frame

;; NOTE: expects to be using the 1st graphics window

(define (move-square time path)

   (let ((winW (car (gfx:get-canvas-size *critter-canvas*)))

         (winH (cdr (gfx:get-canvas-size *critter-canvas*)))

         (pathX (car (gfx:get-path-bounds path)))

         (pathY (cadr (gfx:get-path-bounds path)))

         (x (random -20 21))

         (y (random -20 21)))

      (cond ((> (+ pathX x) (- winW 100)) (set! x -20))

            ((> (+ pathY y) (- winH 100)) (set! y -20))

            ((< (- pathX x) 20) (set! x 20))

            ((< (- pathY y) 20) (set! y 20)))

      (gfx:move-path time path x y)))


;; wipe critters tails over time

(define (clearer time colour)

   (gfx:clear-canvas time *critter-canvas* colour)

   (if *go* (callback (+ time 10000) 'clearer (+ time 22050) colour)))


;; draw critters

(define (drawer time path au:node m fill stroke param-x param-y)

   (gfx:draw-path time *critter-canvas* path stroke fill)

   (let ((x (/ (car (gfx:get-path-bounds path))

               (car (gfx:get-canvas-size *critter-canvas*))))

         (y (/ (cadr (gfx:get-path-bounds path))

               (cdr (gfx:get-canvas-size *critter-canvas*)))))

      (au:set-param (now) au:node param-x 0 0 (* x m))

      ;; (print " x m = " (* x m) " y m =" (* y m))

      (au:set-param (now) au:node param-y 0 0 (* y m))

      (move-square (+ time 10) path)

      (if *go* (callback (+ time 1000) 

                         'drawer 

                         (+ time 2000) 

                         path au:node m fill stroke param-x param-y))))


;; Setup three critters to be started at 1 minute intervals

;; each critter controls two parameters and a primary colour

(define (start time)

   (set! *go* #t)

   (au:start-sound (+ time 100) automat 60 80)

   (drawer time

           (gfx:make-circle 200 200 30)

           automat

           1.0

           (list 0.5 0.0 0.0 0.5)

           (list 0.3 0.0 0.0 1.0) 69 21) ; cutoff and volume

   (drawer (+ time (* *second* 30))

           (gfx:make-circle 200 200 30)

           automat

           24.0

           (list 0.0 0.5 0.0 0.5)

           (list 0.0 0.3 0.0 1.0) 14 20) ; tune and pan

   (drawer (+ time *minute*)

           (gfx:make-circle 200 200 30)

           automat

           1.0

           (list 0.0 0.0 0.5 0.5)

           (list 0.0 0.0 0.3 1.0) 19 17) ; ring mod and glide

   (gfx:clear-canvas time *critter-canvas* '(0.0 0.0 0.0 1.0))

   (clearer time '(0.0 0.0 0.0 0.2)))


;; Stop the sound

(define (stop)

   (set! *go* #f)

   (au:stop-sound (now) automat 60 0))


(stop)


(start (+ (now) *second*))