我对如何在 common lisp 中设置参数感到困惑,试图设置一个全局变量来在 cl-collider 中生成一堆合成器定义。 此代码有效:
(defs sine
:args ((freq 440)
(lag 0.1))
:sig ((sig (sin-osc.ar (lag.kr freq lag)))
(sig (* sig (amp-comp-a.kr freq))))
:num-channels 2)
但是当我这样做时:
(defparameter *num-channels* 2)
...
:num-channels *num-channels*)
我收到此错误:
The value
*NUM-CHANNELS*
is not of type
REAL
[Condition of type TYPE-ERROR]
产生synthdef的宏是这样的:
(defmacro defs (name &key args sig (num-channels 2) (env :asr) (act :free))
(let ((pan-func nil)
(env-func nil)
(arg-list '((attack 0) (release 0)
(out 0) (pan 0) (amp 1))))
(case num-channels
((nil) (setf pan-func 'sig))
(2 (setf pan-func '(pan2.ar sig pan)))
(4 (setf pan-func '(pan4.ar sig pan)))
(t (setf pan-func `(pan-az.ar ,num-channels sig pan :width width))))
(case env
(:asr (setf env-func `(env-gen.kr (asr attack 1 release) :gate gate :act ,act)))
(:perc (setf env-func `(env-gen.kr (perc attack release) :act ,act))))
(if (not(equal env :perc))
(setf arg-list (append arg-list '((gate 1)))))
(if (> num-channels 4)
(setf arg-list (append arg-list '((width 2)))))
`(defsynth ,name (,@arg-list ,@args)
(let* ((env ,env-func)
,@sig
(sig (* sig env amp))
)
(out.ar out ,pan-func)))))
非常感谢任何帮助!
您需要将
case
表达式放入扩展中,以便它可以在运行时引用变量,而不是尝试在扩展时执行此操作。
(defmacro defs (name &key args sig (num-channels 2) (env :asr) (act :free))
(let ((pan-func nil)
(env-func nil)
(arg-list '((attack 0) (release 0)
(out 0) (pan 0) (amp 1)))
(nc-var (gensym))) ;; prevent multiple executions of num-channels
(case env
(:asr (setf env-func `(env-gen.kr (asr attack 1 release) :gate gate :act ,act)))
(:perc (setf env-func `(env-gen.kr (perc attack release) :act ,act))))
(if (not(equal env :perc))
(setf arg-list (append arg-list '((gate 1)))))
(if (> num-channels 4)
(setf arg-list (append arg-list '((width 2)))))
`(defsynth ,name (,@arg-list ,@args)
(let* ((,nc-var ,num-channels)
(env ,env-func)
,@sig
(sig (* sig env amp))
)
(out.ar out (case ,nc-var
((nil) sig)
(2 (pan2.ar sig pan))
(4 (pan4.ar sig pan))
(t (pan-az.ar ,nc-var sig pan :width width))))))))