首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在普通Lisp中嵌入CSound

在普通Lisp中嵌入CSound
EN

Stack Overflow用户
提问于 2017-05-18 12:46:36
回答 1查看 248关注 0票数 1

我正致力于在Lisp中嵌入CSound。CSound是一个音乐合成(和更多)开源软件。

它有一种相当简单的(脚本)语言。快速启动(10分钟阅读)可在上面的链接。目前,我只是在做作业部分(这是很大一部分的声音语言)。

这是我的密码:

代码语言:javascript
复制
(defparameter *assign-statements* nil)

(defmacro assign (_name value &optional (rate 'i))
  (let* ((name (if (typep _name 'symbol) _name (eval _name)))
         (var (symb (format nil "~(~a~)" rate) name)))
    `(progn 
       (defparameter ,name ',var)
       (defparameter ,var ,value)
       (setf *assign-statements* 
                 (cons (format nil "~A = ~A" ,name ,value) *assign-statements*)))))

(defmacro assign* (&rest args)
  `(progn ,@(mapcar (lambda (arg) (cons 'assign arg)) args)))

(defun opcode-call (opcode &rest args)
  (format nil "~a ~{~a~^, ~}" opcode (mapcar (lambda (arg) 
             (if (stringp arg) 
                 (let ((var (gensym)))
                   (eval (list 'assign (symb (symbol-name var)) arg 'a))
                   (symbol-value (symb (symbol-name var)))) 
                 arg)) 
          args)))

(defmacro op (opcode &rest args)
  `(opcode-call ',opcode ,@args))

为了演示代码所做的工作:

代码语言:javascript
复制
(progn  
  (defparameter *assign-statements* nil)
  (assign* 
    (freq 'p4)
    (amp 'p5)
    (att (+ 0.1 0.1))
    (dec 0.4)
    (sus 0.6)
    (rel 0.7)
    (cutoff 5000)
    (res 0.4 k)
    (env (op madsr (op moogladder freq amp) att dec sus rel) k))
  (format t "~{~A~^~%~}~%" 
      (nreverse *assign-statements*)))

产出:

代码语言:javascript
复制
iFREQ = P4
iAMP = P5
iATT = 0.2
iDEC = 0.4
iSUS = 0.6
iREL = 0.7
iCUTOFF = 5000
kRES = 0.4
aG8707 = MOOGLADDER iFREQ, iAMP
aG8708 = MOOGLADDER iFREQ, iAMP
kENV = MADSR aG8708, iATT, iDEC, iSUS, iREL
NIL  

这在所有方面都是正确的,除了"MOOGLADDER iFREQ,iAMP“出现了两次。

,这是为什么?我不知道它在哪里被评估了两次。如何消除这种重复?

关于守则的注意事项:

  • 它有a,k和i率变量的概念。奇怪的是,这是作为变量符号的前缀实现的。lisp中最接近的对应变量是全局变量。所以我把它实现成这样。然而,为了适应这个速率,我在符号和它的值之间有一个间接的级别。例如,符号'res‘表示它的值'kRes’,而现在符号'kRes‘对于它的值来说是原来的0.4。
  • 宏'op‘和’and *‘分别是操作码调用和赋值的简单包装器。
  • “操作码-调用”是一个函数,因此自动允许正常的顺序计算,从而允许嵌套函数调用,而csound并不(完全)支持这一点。为了解决这一问题,opcode-call通过检查它的类型( string ),在它的param列表中查找任何经过评估的操作码。如果它找到一个字符串,它就用gensym变量替换它。
  • 每个赋值调用都会将赋值添加到赋值语句列表中,然后这些语句将最终用于输出到c人声语言。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-18 14:51:03

ASSIGN允许计算该值两次。见下面的评论。

代码语言:javascript
复制
(defmacro assign (_name value &optional (rate 'i))
  (let* ((name (if (typep _name 'symbol) _name (eval _name)))
         (var (symb (format nil "~(~a~)" rate) name)))
    `(progn 
       (defparameter ,name ',var)
       (defparameter ,var ,value)
       (push (format nil "~A = ~A" ,name ,var)    ; <- use the var
             *assign-statements*))))

试一试:

代码语言:javascript
复制
CL-USER 52 > (progn  
               (defparameter *assign-statements* nil)
               (assign* 
                (freq 'p4)
                (amp 'p5)
                (att (+ 0.1 0.1))
                (dec 0.4)
                (sus 0.6)
                (rel 0.7)
                (cutoff 5000)
                (res 0.4 k)
                (env (op madsr (op moogladder freq amp) att dec sus rel) k))
               (format t "~{~A~^~%~}~%" 
                       (nreverse *assign-statements*)))
iFREQ = P4
iAMP = P5
iATT = 0.2
iDEC = 0.4
iSUS = 0.6
iREL = 0.7
iCUTOFF = 5000
kRES = 0.4
aG2719 = MOOGLADDER iFREQ, iAMP
kENV = MADSR aG2719, iATT, iDEC, iSUS, iREL
NIL
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44048191

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档