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

;;

;; Simple audiofile playback through the ICR

;;

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


(define code (au:make-node "aumu" "code" "MOSO"))

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

(au:update-graph)


;; load audio file

(define adat (au:load-audio-data "/tmp/my.mp3"))


;; retrieve raw floating point audio data from adat

(define audiodat (objc:object-at-index adat 3))


;; bind the raw audio data as a global variable

;; of type float* in the IRC

;;

;; this is the only other way to communicate between Scheme and the IRC

;; 

;; You can only pass Scheme cptr objects such as that

;; returned from the call to (objc:call audiodat "bytes")

;; and must assign a valid IRC pointer type (float* in this case)

(bindc audiodat float* (objc:call audiodat "bytes"))


;; also assign the files number of channels and frames as global vars

(define audiodat2 (objc:data:make (* 8 2)))

(objc:data:set-sint64 audiodat2 0 (objc:get-value-for-key (objc:object-at-index adat 0) "frames"))

(objc:data:set-sint64 audiodat2 1 (objc:get-value-for-key (objc:object-at-index adat 0) "channels"))

;; and bind them

(bindc audiodat2 i64* (objc:call audiodat2 "bytes"))


;; sample playback kernel with randomizing playhead

;; you might want to fiddle with phoffset

;; depending on the length of your audiofile

(definec sample-playback

   (lambda ()

      (let* ((phoffset 600000)

             (playhead phoffset))

         (lambda (freq:double time:double channel:double data:double*)

            (let ((frames (array-ref audiodat2 0))

                  (channels (array-ref audiodat2 1)))

               (if (> (random) (array-ref data 0))

                   (set! playhead (+ phoffset (dtoi64 (* (random) 1000000.0)))))

               (if (= channel 0.0) (set! playhead (+ playhead 1)))

               (ftod (array-ref audiodat (+ playhead (* (dtoi64 channel) frames)))))))))


;; set playback kernel

(au:code:set! code "sample-playback")


;; set randomize parameter to 1.0 (not randomized)

(au:set-param (now) code 3 *au:global-scope* 0 1.0)

;; play a note

(play-note (now) code 60 80 (* *second* 30.0))

;; randomize the playback head

(au:set-param (now) code 3 *au:global-scope* 0 0.9999)