CL-Collider中使用全局变量设置num-channels参数报错求助
解决CL-Collider中使用全局变量设置:num-channels的类型错误
问题原因
你的问题核心在于宏的编译期求值特性:
- 直接传入
:num-channels 2时,宏在编译阶段拿到的是数值2,后续的case判断、> num-channels 4比较都能正常执行,生成的合成器代码符合CL-Collider的要求。 - 传入
:num-channels *num-channels*时,宏在编译阶段拿到的是符号*NUM-CHANNELS*而非它的数值2:case判断找不到匹配分支,进入默认分支,将符号直接插入到pan-az.ar的参数列表中;> num-channels 4是用符号和数字做比较,编译阶段不会报错,但生成的合成器代码运行时,CL-Collider要求pan-az.ar的第一个参数为REAL类型,符号显然不符合,因此抛出类型错误。
解决方法
修改defs宏,在编译阶段对num-channels参数求值,确保拿到的是实际数值而非符号。修改后的宏代码如下:
(defmacro defs (name &key args sig (num-channels 2) (env :asr) (act :free)) (let* ((num-channels-val (eval num-channels)) ; 关键:编译期求值num-channels参数 (pan-func nil) (env-func nil) (arg-list '((attack 0) (release 0) (out 0) (pan 0) (amp 1)))) (case num-channels-val ((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-val 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-val 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)))))
使用验证
先定义全局变量:
(defparameter *num-channels* 2)
再调用defs宏时传入:num-channels *num-channels*,宏会在编译阶段自动获取全局变量的数值2,生成与直接传入数值完全一致的合成器定义,运行时不再出现类型错误。
内容的提问来源于stack exchange,提问作者kflak
相关产品推荐
相关产品推荐

