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

;;

;; On the fly audio-signal-processing

;;

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


(define aucode1 (au:make-node "aumf" "code" "MOSO"))

(define aucode2 (au:make-node "aumf" "code" "MOSO"))

(define aucode3 (au:make-node "aumf" "code" "MOSO"))

(define mix (au:make-node "aumx" "smxr" "appl"))

(au:connect-node aucode1 0 aucode3 0)

(au:connect-node aucode3 0 mix 0)

(au:connect-node aucode2 0 mix 1)

(au:connect-node aucode3 0 mix 1)          

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

(au:update-graph)


;; simplest of the simple - whitenoise

(au:code:load aucode1 "dsp" (lambda (sample time channel data)

                               (* 0.1 (random))))



;; sinewave with phase information maintained

(define sinewave

   (lambda (sample time channel data)

      (let ((phase (objc:data:get-double data channel))

            (freq (objc:data:get-double data 2))

            (inc (* 2.0 3.141592 (/ freq 44100))))

         (objc:data:set-double data channel (+ inc phase))

         (* 0.3 (sin (+ inc phase))))))


;; create a data object to share with aucode1

(define dat (objc:data:make (* 8 3)))

;; set frequency in dat[2] save dat[0] and dat[1] for left and right phase

(objc:data:set-double dat 2 220.0)

;; load sinewave with dat into aucode1

(au:code:load aucode1 sinewave dat)


;; define simple fm

(define fm

   (lambda (sample time channel data)

      (let ((carrier-freq (objc:data:get-double data 4))

            (mod-freq (objc:data:get-double data 5))

            (carrier-phase (objc:data:get-double data (+ channel 0)))

            (mod-phase (objc:data:get-double data (+ channel 2)))

            (mod-width (objc:data:get-double data 6))

            (carrier-inc 0.0)            

            (mod-inc 0.0))

         (set! mod-inc (sin (* 3.141592 2 (/ mod-freq 44100))))  

         (set! carrier-inc (sin (* 3.141592 2 (/ carrier-freq 44100))))                            

         (objc:data:set-double data (+ channel 0) (+ carrier-inc carrier-phase))

         (objc:data:set-double data (+ channel 2) (+ mod-inc mod-phase)) 

         (* .5 (cos (+ carrier-phase carrier-inc (* mod-width (cos (+ mod-phase mod-inc)))))))))


;; create a data object to share with aucode1

(define dat2 (objc:data:make (* 8 7)))

;; set frequency in dat[4] save dat[0-3] for phase information 

(objc:data:set-double dat2 4 180.0)

(objc:data:set-double dat2 5 (* 180 2.5))

(objc:data:set-double dat2 6 0.5)

;; load sinewave with dat into aucode1

(au:code:load aucode2 fm dat2)


;; play frequencies - carrier with mod ratio

(define loop1

   (lambda (beat) 

      (let ((freq (random 60 480)))

         (objc:data:set-double dat2 4 freq)

         (objc:data:set-double dat2 5 (* 2.5 freq))

         (callback (*metro* (+ beat (* .98 8))) 'loop1 (+ beat 8)))))


(loop1 (*metro* 'get-beat 4))



;; and loop 2 fast for mod-width

(define loop2

   (lambda (beat) 

      (objc:data:set-double dat2 6 (cosr 0.5 0.4 1/8))      

      (callback (*metro* (+ beat (* .5 1/32))) 'loop2 (+ beat 1/32))))


(loop2 (*metro* 'get-beat 4))



;; An example which operates as an effect

;; rather than a generator (i.e. effects an incoming signal)

;;

;; A simple low-pass filter

;;

;; first go back and redefine the original noise signal for aucode1

;;

;; there are aliases for setting and getting data objects

;; float 64 bit set = f64s = objc:data:set-double

;; float 64 bit get = f64g = objc:data:get-double


(define filter

   (lambda (sample time channel data)

      (let ((frequency (f64g data 0))

            (p0 (f64g data 1))

            (p1 (f64g data 2)))

         (set! p0 (+ p0 (* frequency (- sample p0))))

         (set! p1 (+ p1 (* frequency (- p0 p1))))

         (f64s data 1 p0)

         (f64s data 2 p1)  

         p1)))


(define filter-dat (objc:data:make (* 8 3)))

;; don't push frequency higher than 1.0

(objc:data:set-double filter-dat 0 0.5)


(au:code:load aucode3 "filter" filter filter-dat)


;; filter frequency sweep

(define loop3

   (lambda (beat) 

      (objc:data:set-double filter-dat 0 (cosr .5 .4 1/12))

      (callback (*metro* (+ beat (* .5 1/32))) 'loop3 (+ beat 1/32))))


(loop3 (*metro* 'get-beat 4))