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

;;

;; PLAY A BACH 4 PART CHORALE

;;

;; NOTE: You will need to point the 

;; (io:read-midi-file "somefile.mid") function to 

;; a valid 4 part midi file.

;;

;; You can download a chorale from here

;; http://mapage.noos.fr/dardelf/musique/BWV645.mid

;;

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


;; Make sure that no audio units are already connected

(au:clear-graph)


;; setup audio unit graph

(define synth (au:make-node "aumu" "dls " "appl"))

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

(au:update-graph)


;; send program change to dls audio units

(au:midi-out (now) synth *io:midi-pc* 0 68 0) ; oboe

(au:midi-out (now) synth *io:midi-pc* 1 71 0) ; clarinet

(au:midi-out (now) synth *io:midi-pc* 2 60 0) ; horn

(au:midi-out (now) synth *io:midi-pc* 3 70 0) ; bassoon


;; read midi file

(define chorale (io:read-midi-file "/tmp/bach.mid"))


;; Play a MIDI track

; The list-ref function is an Impromptu function that 

; allows the acceesing of elements within a list by index.

; The consing of the play-note time and marker attaches

; the marker number of the note events (start and stop).

(define (play-seq time inst midi-track chan)

   (map (lambda (t p v r)

           (play-note (+ time (* t *second*)) inst p v (* r *second*) chan))

        (list-ref midi-track 0)        

        (list-ref midi-track 1)

        (list-ref midi-track 2)

        (list-ref midi-track 3)))


;; Play the first four tracks

(define (chorale-player time score)

   (play-seq time synth (list-ref score 0) 0))

   (play-seq time synth (list-ref score 2) 1)

   (play-seq time synth (list-ref score 1) 2)

   (play-seq time synth (list-ref score 0) 3))

      

;; Start - give play-seq 2 seconds to load the file.

(chorale-player (+ (now) (* *second* 2)) chorale)