;;; Additive synthesis instrument 
;;; using the data in spectr.clm
;;; primitive Spectral Modelling
;;; with frozen spectral data
;;; Juan Pampin
;;; juan@ccrma.stanford.edu

(definstrument madd (start-time duration frequency amplitude spectrum 
				&optional (envelope '(0 1 1 1)))
  (multiple-value-bind (beg end) (get-beg-end start-time duration)
    (let* ((partials (/ (list-length spectrum) 2))
           (osc-array (make-array  partials :element-type 'osc))
           (amp-array (make-array  partials))
	   (amp-env (make-env :envelope envelope :scaler amplitude)))
      ;;; initialize the arrays...
      (loop for n from 0 below partials do
            ;;; create one oscillator and store it in the array
	    (setf (aref osc-array n) 
		  (make-oscil :frequency (* frequency (nth (* 2 n) spectrum))))
            ;;; store amplitude in other array
	    (setf (aref amp-array n) 
		  (nth (+ 1 (* 2 n)) spectrum)))
      ;;; by now we have everything ready to compute the samples...
      (run
       (loop for i from beg to end do
         (let ((sum 0.0))
	   (loop for j from 0 below partials do
             (incf sum (* (aref amp-array j) (oscil (aref osc-array j)))))
           (outa i (* (env amp-env) sum))))))))

#|
;;; load all spectral data first
(load "/usr/ccrma/lisp/src/clm/spectr.clm")

;;; play a bass clarinet tone
;;; no envelope
(with-sound ()
  (madd 0.0 5.0 (pitch 'c2) 0.5 bc-c2))
;;; try to get something better using 
;;; an envelope
(with-sound ()
  (madd 0.0 5.0 (pitch 'c2) 0.5 bc-c2 '(0 0 0.01 1 0.03 0.707 0.8 0.707 1.0 0.0)))

(with-sound ()
  (madd 0.0 5.0 (pitch 'c2) 1.0 p-c2 '(0 0 0.001 1 0.003 0.5 0.5 0.07 0.8 0.01 1.0 0.0)))

(with-sound ()
  (madd 0.0 5.0 (pitch 'c2) 1.0 p-c2 (append '(0 0.0 0.001 1.0) 
					     (env-exp '(0.003 0.5 1 0.0) 3 10.0) '(1 0.0))))
|#
