Common-lisp:整数不是实数类型

问题描述 投票:0回答:1

我对如何在 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)))))

非常感谢任何帮助!

common-lisp
1个回答
1
投票

您需要将

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))))))))
© www.soinside.com 2019 - 2024. All rights reserved.