Problem with using macro in CLM run

Larry Troxler lt@westnet.com
Thu, 4 Sep 1997 20:14:55 -0400 (EDT)


Sorry, this will be a bit long, and it's probablysome problem on
my part,
but I just wanted to check that it's not a problem with CLM.

In the following code, when I call my exp-glide macro inside run, the
compilation fails with:

; Writing "/p2/usr/local/cm/clm_lnxacl_BUGAPHONE.c"
; While compiling (:TOP-LEVEL-FORM "inses.lisp" 1389):
Error: CLM's DSP library cannot handle EXCL::.INV-S-AREF in
       (EXCL::.INV-S-AREF #:G16594 #:G16592 #:G16593)

However, if I macroexpand-1 the call from top-level, and paste it in the
code, everything works. Here's the code:

;;; Bugaphone:
;;; A buggy additive synthesis instrument, using exponential slopes
between
;;; successive spectra. Hopefully the name will change ...

;;; Glide the setf-form "var" exponentially with time-constant "tau" 
;;; from its curent value towards "target". 
;;; tau=0 results in immediate var=target.
(defmacro exp-glide (var tau target)
  `(incf 
    ,var 
    (* 
     (- ,target ,var) 
     (/ 1.0 (max 1.0 (* ,tau sampling-rate))))))

;;; The "spec" parameter to this instrument is a list of "slices" of
;;; the form:
;;;  ( <seconds to compute on this slice>
;;;  ( {<target amp for nth partial> <tau for exp slope rate to target
amp>}*))
;;; 
;;; Or, it can also be a function that computes such a form, in which case
;;; it is passed the event's duration, frequency, amplitude, and whatever
;;; other args are passed in as the "args" parameter.
;;; 

;;; Using macros in case I want to change the above structure.
(defmacro slice-dur (slice)
  `(nth 0  ,slice))
(defmacro slice-target-n (slice n)
  `(nth (* 2 ,n) (nth 1 ,slice)))
(defmacro slice-tau-n (slice n)
  `(nth (1+ (* 2 ,n)) (nth 1 ,slice)))


;;; start = start time in seconds
;;; d = duration in seconds
;;; f = A Common Music note, degree, or pitch
;;; a = overall amplitude scaler.
;;; spec = List of slices as described above, or function to compute same.
;;; args = additional args to pass to spec function.
(definstrument bugaphone (start d f a &key spec args)
  (let*
      ((beg (floor (* start sampling-rate)))
       (end (+ beg (floor (* d sampling-rate))))
       (f (pitch f))			; should really conditionallize 
					; this here using features
					; (for non-CM people)
       ;; Allow spec to be either a direct spec list, a symbol for
       ;; such a list, or a function that computes one.
       (spec 
	(cond ((consp spec) spec)
	      ((symbolp spec) (symbol-value spec))
	      ((functionp spec) 
	       (apply spec d f a args))))
       (n-slices (length spec)) 
       (n-harmonics (/ (length (second (first spec))) 2)) ; All slices
should
					; specify the same # of harmonics!
       (cur-slice-number -1)		; will get bumped to zero pronto
       (cur-slice-sample-count  0)	; samples left for current slice
       (oscs (make-array n-harmonics))
       (amps (make-array n-harmonics :initial-element 0.0))
       (durs (make-array n-slices))
       (taus (make-array (list n-slices n-harmonics)))
       (targets (make-array (list n-slices n-harmonics))))
       
    ;; Set up oscils and copy stuff from spec lists into arrays for run
    (loop for harmonic below n-harmonics do
	  (setf (aref oscs harmonic) (make-oscil (* (1+ harmonic) (pitch
f)))))
    (loop for slice below n-slices do
	  (setf (aref durs slice) (slice-dur (nth slice spec)))
	  (loop for harmonic below n-harmonics do
		(setf (aref taus slice harmonic)
		  (slice-tau-n (nth slice spec) harmonic))
		(setf (aref targets slice harmonic)
		  (slice-target-n (nth slice spec) harmonic))))
    ;; for debugging
    (print durs)
    (print taus)
    (print targets)

    (run
     (loop for samp from beg to end do
	   ;; "cur-slice-sample-count" tracks the time spent
	   ;; on each slice.
	   (when (zerop cur-slice-sample-count)
	     (incf cur-slice-number)
	     (setf cur-slice-sample-count 
	       (max 1 (* (aref durs cur-slice-number) sampling-rate)))
	     (print (aref taus cur-slice-number 0))) ; <- debugging

	   (decf cur-slice-sample-count) ; tick-tock

	   (loop for harmonic below n-harmonics do
		 ;; This macro call chokes the CLM DSP compiler!!
		 (exp-glide (aref amps harmonic) 
			    (aref taus cur-slice-number harmonic)
			    (aref targets cur-slice-number harmonic))
		 
		 ;; but the following, pasted from macroexpand-1
		 ;; at top-level, works!!
;;;		 (INCF (AREF AMPS HARMONIC)
;;;		       (* (- (AREF TARGETS CUR-SLICE-NUMBER HARMONIC)
(AREF AMPS HARMONIC))
;;;			  (/ 1.0 (MAX 1.0 (* (AREF TAUS CUR-SLICE-NUMBER
HARMONIC) 22050)))))


		 (outa samp 
		       (* a 
			  (aref amps harmonic) 
			  (oscil (aref oscs harmonic)))))))))

(make-instance 'i1)			; Hack for CM


--  Larry Troxler  --  lt@westnet.com  --  Patterson, NY USA  --