; create and hook up an instrument

(define dls (au:create-node "aumu" "dls " "appl"))

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

(au:update-graph)

(au:open-view dls)


; set an inital value for the pitch to play

(define *pitch* 60)


; continuously play a note of pitch *pitch*

(define notes

   (lambda (time)

      (play-note time dls *pitch* 80 4410)

      (callback (+ time 4000) 'notes (+ time 4410))))


; repeatedly poll the light sensors, setting the global variable *pitch* accordingly 

(define poll-light-sensors

   (lambda (time)

      ; set left to the value of the left light sensor

      ;     right to the valu of the right light sensor

      ;     semitone to a value in the range 0..11, based on the value of the left light sensor

      ;     octave to a value in the range 0..3, based on the value of the right light sensor

      ;     note that the max light sensor value seems to be around 1050, but the sensor is much

      ;       more sensitive close to the lower end of the scale, so we only use the range 0..500

      (let* ((left (objc:call light-sensor "leftSensorReading"))

             (right (objc:call light-sensor "rightSensorReading"))

             (semitone (* (/ (- left 500) 500) 11))

             (octave (* (/ (- right 500) 500) 3)))

         ; ensure 0 <= semitone <= 11

         (set! semitone (real->integer semitone))

         (set! semitone (min semitone 11))

         (set! semitone (max semitone 0))

         

         ; ensure 0 <= octave <= 3

         (set! octave (real->integer octave))

         (set! octave (min octave 3))

         (set! octave (max octave 0))

         

         ; pitch

         (let ((pitch (+ semitone (* octave 12) 36)))

            ;(print left right octave semitone pitch)

            (if (or (< left 0) (< right 0))

                (print "light sensor is unavailable. try using (objc:call light-sensor \"setMinUpdateInterval:\" new-min-interval) where new-min-interval is higher than " (objc:call light-sensor "minUpdateInterval"))         

                (set! *pitch* pitch)))

         

         (callback (+ time 2000) 'poll-light-sensors (+ time 3000)))))



; load the light sensor bundle

(define light-sensor-bundle (objc:call "NSBundle" "bundleWithPath:" "/full/path/to/LightSensorBundle.bundle"))


; load the light sensor class from the bundle

(define light-sensor-class (objc:call light-sensor-bundle "classNamed:" "LightSensor"))


; instantiate a light sensor object

; we pass it the objective-c bridge singleton object which the LightSensor

;  object uses to query the current sample (ie the result of evaluating the function now)

(define light-sensor (objc:make "LightSensor" "initWithBridge:" *impromptu-objc-bridge*))


; print the current value of the left and right light sensors

(print (objc:call light-sensor "leftSensorReading"))

(print (objc:call light-sensor "rightSensorReading"))


; update the minimum elapsed time before which the light sensor object will

;  re-query the current value of the light sensors

(objc:call light-sensor "setMinUpdateInterval:" 1000)


; kick it all off

(poll-light-sensors (now))

(notes (now))