
(define *srate* 44100)
;; Additive instrument with 3 oscillators and 3 individual amplitude envelopes
;; This instrument is built with arrays as the appropriate way when having MANY oscillators.
(definstrument (additive-arrays start-time duration freq1 freq2 freq3 amp1 amp2 amp3)
  "Additive instrument with 3 oscillators and 3 individual amplitude envelopes"
  (let* ((start-sample (* start-time *srate*))
         (end-sample (+ start-sample (* duration *srate*)))
         (oscil-array (make-vector 3))
         (amp-array (make-vector 3))
         (freq-array (make-vector 3)))
    (vector-set! oscil-array 0 (make-oscil :frequency 0))
    (vector-set! oscil-array 1 (make-oscil :frequency 0))
    (vector-set! oscil-array 2 (make-oscil :frequency 0))
    (vector-set! amp-array 0 (make-env :envelope amp1 :duration duration))
    (vector-set! amp-array 1 (make-env :envelope amp2 :duration duration))
    (vector-set! amp-array 2 (make-env :envelope amp3 :duration duration))
    (vector-set! freq-array 0 (make-env :envelope freq1 :duration duration :scaler (hz->radians 1)))
    (vector-set! freq-array 1 (make-env :envelope freq2 :duration duration :scaler (hz->radians 1)))
    (vector-set! freq-array 2 (make-env :envelope freq3 :duration duration :scaler (hz->radians 1)))
    ; hz->radians is frequency in radians per OUTPUT sample: (/ (* frequency 2 pi) *srate*)
     (do ((index start-sample (+ index 1)))
         ((>= index end-sample))
       (outa index (+ (* (env (vector-ref amp-array 0))
                         (oscil (vector-ref oscil-array 0) (env (vector-ref freq-array 0))))
                      (* (env (vector-ref amp-array 1))
                         (oscil (vector-ref oscil-array 1) (env (vector-ref freq-array 1))))
                      (* (env (vector-ref amp-array 2))
                         (oscil (vector-ref oscil-array 2) (env (vector-ref freq-array 2)))))))))



#|
(with-sound (:srate 44100 :scaled-to .99 :statistics #t)
  (let* ((notes 20) ; number of note calls ;
         (start 0) ; initial start time	;
         (dur 0.3))
    (do ((i 1 (+ i 1)))
        ((> i notes))
      (additive-arrays start dur
                       (list 0 110 1 220)
                       (list 0 330 1 660)
                       (list 0 550 1 1100)
                       (list 0 0 0.1 0.33 1 0)
                       (list 0 0 0.2 0.33 1 0)
                       (list 0 0 0.3 0.33 1 0))
      (set! start (+ start (* 1.5 dur))))))


|#

