'(print
  (control-srate-abs 20
    (snd-samples 
      (snd-trigger (lfo 2) '(lambda (t0) (at-abs t0 (const 0.5 0.2))))
      100)))

'(print
  (control-srate-abs 20
    (snd-samples 
      (trigger (lfo 2) (const 0.5 0.2))
      100)))

(defmacro trigger (input beh)
  `(let* ((nyq%environment (nyq:the-environment))
          (s%rate *sound-srate*))
     (snd-trigger (force-srate *sound-srate* ,input)
                  #'(lambda (t0) (eval-seq-behavior ,beh "TRIGGER")))))

(setf *gc-flag* t)
(setf *breakenable* t)

(autonorm-off)

(pprint (macroexpand '(trigger (snd-offset (sound-srate-abs 20 (noise dur))
                                           -0.9)
                               (pluck (+ 48 (random 24))))))


(setf pitch-pat (make-heap '(60 62 65 67 70 72 74 77 79 82 84)))

;; make a big sound with trigger so we can see if there is
;; retention in memory
'(defun trigger-test (dur)
  (play (scale 0.25 (trigger (snd-offset (sound-srate-abs 40 (noise dur))
                                        -0.9)
                            (scale (+ 0.1 (rrandom))
                                   (pluck (next pitch-pat)))))))

'(defun trigger-test (dur)
  (play (trigger  (pwl 1 0 2 1 3 0 4 1 5) (pluck c4))))

(defun make-trigger-input ()
 (force-srate *sound-srate*
  (vector (snd-offset (sound-srate-abs 40 (noise 600)) -0.9)
          (snd-offset (sound-srate-abs 40 (noise 600)) -0.9))))

(defun trigger-snd (input)
  (trigger input (pluck c4)))

'(trigger-test 20)
;; Legacy version:
(defun multichan-expand-old (fn &rest args)
  (let (len newlen result) ; len is a flag as well as a count
    (dolist (a args)
        (cond ((arrayp a)
           (setf newlen (length a))
           (cond ((and len (/= len newlen))
              (error (format nil "In ~A, two arguments are vectors of differing length." fn))))
           (setf len newlen))))
    (cond (len
       (setf result (make-array len))
       ; for each channel, call fn with args
       (dotimes (i len)
           (setf (aref result i)
             (apply fn
            (mapcar
                #'(lambda (a)
                ; take i'th entry or replicate:
                (cond ((arrayp a) (aref a i))
                      (t a)))
                args))))
       result)
      (t
       (apply fn args)))))

(defmacro audacity (snd)
  `(s-save (let ((s ,snd)) (setf *track* nil) s) ny:all "temp.wav"))

(setf *track* (make-trigger-input))

'(print (macroexpand '(multichan-expand-old #'trigger-snd *track*)))

'(audacity (multichan-expand-old #'trigger-snd *track*))

'(s-save (multichan-expand "test" #'trigger-snd '(((sound) "input"))
                          (make-trigger-input))
        ny:all "temp.wav")

;; this is what steve says works with stereo:
(defmacro with%environment-hack (env &rest expr)
  `(progv ',*environment-variables* ,env ,@expr))
 
(defmacro trigger2 (input beh)
  `(let ((nyq%environment (nyq:the-environment)))
     (snd-trigger ,input #'(lambda (t0) (with%environment-hack nyq%environment
                                                (at-abs t0 ,beh))))))

;; my guess at getting it to work with stereo
(defun test (snd) (trigger2 snd (stretch-abs 1 (pluck c4))))

(audacity (multichan-expand-old #'test *track*))


(defun re () (load "trigger"))

