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 --