;; Player Instrument for Genetic code mutation 
(defparameter *INS-DEBUG* nil)

(definstrument gene-play (seq start-time duration)
  (multiple-value-bind (beg end) (get-beg-end start-time duration)
    (let ((playfunc (gene-output-function-generator seq)))
      (loop for i from beg to end do 
	(outa i (funcall playfunc))
	 )
      )
))

; generic

(defun create-output-function (seq)
  (let* ((subtype (first seq))
	 (generatorfunc (get-output-generator-func-name subtype)))
    (if *INS-DEBUG* (format t "create-out-func:  ~s  type ~s  func ~s~%" seq subtype generatorfunc))
    (funcall generatorfunc seq))
)

(defun get-output-generator-func-name (typename)
  (let ((funcname nil))
    (if (eql typename 'SINE) (setf funcname 'sine-output-function-generator))
    (if (eql typename 'GENE) (setf funcname 'gene-output-function-generator))
    (if (eql typename 'AMP) (setf funcname 'amp-output-function-generator))
    (if (eql typename 'FIXED) (setf funcname 'fixed-output-function-generator))

    (if (not funcname)
	(error "Error: ~s is not a know sequence type!~%" typename)
      funcname))
)



(defun gene-output-function-generator (seq)
  (if (not (> (length seq) 1)) (error "Error: invalid format for gene sequence - ~s~%" seq))
  (if (not (eql (first seq) 'gene)) (error "Error: invalid format for gene sequence - ~s~%" seq))
  (let ((outfuncs '()))
    (loop for el in seq do
	(if (not (eql el 'GENE))
	    (if outfuncs 
		(setf outfuncs (append outfuncs (list (create-output-function el))))
	      (setf outfuncs (list (create-output-function el))) 
	      )))
    (lambda () (reduce '+ (map 'list #'funcall outfuncs)))
    )
)


(defun sine-output-function-generator (seq)
  (if (not (eq (length seq) 2)) (error "Error: invalid format for sine sequence - ~s~%" seq))
  (if (not (eql (first seq) 'sine)) (error "Error: invalid format for sine sequence - ~s~%" seq))
 
  (let* ((freqfunc (create-output-function (second seq)))
	(osc (make-oscil (funcall freqfunc))))
    (if *INS-DEBUG* (format t "sine-create:  creating oscil with f ~d~%" (funcall freqfunc)))
    (lambda () (* 0.5 (oscil osc)))
    )
)

(defun fixed-output-function-generator (seq)
  (if (not (eq (length seq) 2)) (error "Error: invalid format for fixed sequence - ~s~%" seq))
  (if (not (eql (first seq) 'fixed)) (error "Error: invalid format for fixed sequence - ~s~%" seq))

  (let ((val (second seq)))
    (lambda () val)
    )
)

(defun amp-output-function-generator (seq)
  (if (not (eq (length seq) 3)) (error "Error: invalid format for amp sequence - ~s~%" seq))
  (if (not (eql (first seq) 'amp)) (error "Error: invalid format for amp sequence - ~s~%" seq))

  (let* ((scalingfunc (create-output-function (second seq)))
	 (signalfunc (create-output-function (third seq))))
    (if (eql (first (second seq)) 'FIXED)
	(lambda () (* (/ (funcall scalingfunc) *AMP-FIXED-RANGE*) (funcall signalfunc)))
	(lambda () (* (funcall scalingfunc) (funcall signalfunc)))
    ))
)
