1 Audacity插件开发:Nyquist快速参考
1.1 Audacity和Nyquist
1.1.1 Nyquist,XLisp的超集
在Lisp(Nyquist也同样如此)中,所有内容都是S表达式。S表达式是由空格分隔并括在括号内的一系列标记(单词)。函数名始终是S表达式中的第一个标记,其他所有标记都是该函数的参数。下面是一个简单的例子:
(setf area (* 3.14159 (expt radius 2)))
让我们剖析这个例子。最外层的S表达式有三个成员。第一个是setf
,它是函数名(它代表“set - field” )。setf
用于将一个值赋给一个变量。(还有其他类似的函数,如set
和setq
,但setf
功能最强大,所以在我们的示例中会使用它。)接下来是我们要设置的变量的名称area
。最后是要赋给这个变量的值。
Lisp没有针对数学函数的特殊运算符——它们都和其他所有函数一样,使用前缀表示法,即函数名在参数之前。所以在Lisp中,要计算3和7的乘积,你不会写成3*7
,而是写成(* 3 7)
。在Nyquist中,expt
(指数)函数将其第一个参数提升到第二个参数的幂次。因此,(* 3.14159 (expt radius 2))
表示3.14159乘以半径的平方,即圆的面积公式。
与其每次都输入这个完整表达式,不如定义一个求圆面积的函数,方便随时调用:
(defun circlearea (radius) (* 3.14159 (expt radius 2)))
defun
函数用于定义一个新函数。第一个参数是函数名,在这个例子中是circlearea
。第二个参数是函数要使用的变量列表。这是少数几种S表达式不会被解释为函数调用的情况之一。最后,最后一个表达式是函数的返回值。现在,如果我们想计算半径为r
的圆的面积,只需计算:
(circlearea r)
S表达式只是列表的一种表示形式。Lisp使用列表来表示几乎所有内容(LISP这个名字就来源于“LISt Processing language”,即列表处理语言 )。
所以,如果你想通过给变量赋值一个数字列表来了解Lisp如何操作列表,你不能这样写:
(setf mylist (1 2 3 4 5)) ; 错误!
这样写不行的原因是,只要Nyquist看到一个S表达式,它就会尝试将其作为函数进行求值,除非你另有指示。由于没有名为1
且接受参数(2 3 4 5)
的函数,这将产生错误。要告诉Lisp你想按字面意思处理一个S表达式,而不是将其作为函数求值,你需要对其进行引用。在Nyquist中,你可以在列表前加上一个单引号来引用它,如下所示:
(setf mylist '(1 2 3 4 5))
Nyquist还提供了list
函数,你可以用它来构建列表——如果列表的某些元素是函数,这会很有用:
(setf mylist (list 1 2 3 4 (sqrt 25)))
要获取列表的元素,你可以使用first
和rest
函数。(传统上,它们分别被称为car
和cdr
,但first
和rest
更容易记忆。Nyquist中同时支持这两组名称 )。(first mylist)
的输出是1,(rest mylist)
的输出是列表(2 3 4 5)
。所以列表的第二个元素是(first (rest mylist))
。
1.1.2 Lisp函数参考
以下是一些你可能需要用到的基本Lisp函数列表。
1.1.2.1 数学函数
(+ a b)
:加法(- a b)
:减法(* a b)
:乘法(/ a b)
:除法(truncate a b)
:向下取整为整数(地板函数)(float a b)
:转换为浮点数(rem a b c...)
:求余数(min a b c...)
:求最小值(max a b c...)
:求最大值(abs a)
:求绝对值(random n)
:生成1到n - 1之间的随机整数(sin a)
:正弦(cos a)
:余弦(tan a)
:正切(expt a b)
:指数(a的b次幂)(sqrt a)
:平方根(< a b)
:测试a是否小于b(<= a b)
:测试a是否小于或等于b(> a b)
:测试a是否大于b(>= a b)
:测试a是否大于或等于b(= a b)
:测试是否相等(/= a b)
:测试是否不相等
1.1.2.2 列表函数
(first l)
:列表的第一个元素(car)(rest l)
:列表的其余部分(cdr)(reverse l)
:反转列表(list a b...)
:构建一个列表(append l1 l2)
:连接两个列表(length l)
:获取列表长度(maplist function l)
:对列表中的每个元素应用一个函数
1.1.3 控制
(if expr expr1 expr2)
:如果expr为真,计算expr1,否则计算expr2
欲获取完整的Lisp / Nyquist函数列表,请查看《Nyquist参考手册》。
注意:Nyquist中的符号(如变量名和函数名)不区分大小写。它们在内部会被转换为大写形式。
1.2 用Nyquist编程
Nyquist与Lisp的不同之处在于,它专为处理声音而设计,拥有大量用于合成、分析和处理声音的内置原语和函数。在Audacity中,借助Nyquist丰富的内置函数,相对容易构建复杂的音效。
在Nyquist中,变量可以像握住绳子或琴弦一样稳定地保存声音。它提供了一系列函数,允许你拉伸、扭曲和组合声音,甚至可以逐样本访问声音,但这超出了本教程的范围。
要在Audacity中运行Nyquist表达式,可以使用“效果”菜单中的“Nyquist Prompt”。你选择的任何音频都将存储在变量s
中,你输入的Nyquist表达式的结果将替换所选内容。在本页面的下方,你将学习如何使用Nyquist创建插件效果。
1.2.1 声音合成
以下函数都可创建新声音。你可以用它们创建“生成”插件效果,也可以将这些合成声音与选定音频结合,产生有趣的音效。
(noise)
:生成白噪声(const value [duration])
:生成恒定(无声)信号(sine pitch [duration])
:生成指定音高和时长的正弦波。音高为MIDI音符编号,中央C为60 。(oscil-hz [duration])
:生成指定频率(赫兹)的正弦波(oscil-tri hz)
:生成指定频率(赫兹)的三角波(oscil-pulse hz bias)
:生成指定频率(赫兹)的可变方波。偏置参数控制脉冲宽度,范围从0%(始终为 -1)到100%(始终为 +1)。偏置为零时,生成普通方波。(pluck pitch)
:使用改良的卡普拉斯 - 斯特朗弹拨弦算法,生成指定音高的声音
1.2.2 包络
Nyquist支持包络。将包络应用于声音,你可以控制其振幅的整体形状。构建包络最简单的方法之一是使用env
函数,它接受7个参数,这些参数常用于塑造合成音符:起音时间、衰减时间、释放时间、起音电平、衰减电平、持续电平以及总时长。见下图:
要将包络应用于声音,只需使用mult
函数。所以,如果s
是一个声音,那么以下是应用了简单包络的声音:
(mult s (env 0.1 0.2 1.0 0.5 0.3 1.0))
最常见的包络类型之一是分段线性函数,可使用pwl
函数构建。pwl
函数接受一系列参数,这些参数表示(时间,值)对。隐含的起始点为(0, 0),隐含的结束值为0。参数的数量必须为奇数,因为最后一个时间是隐含的。例如:
; 在时间1达到0.7(对称斜坡)并在时间2回到0
(pwl 1.0 0.7 2.0 0)
1.2.3 声音组合
除了使用mult
函数将两个声音相乘,你还可以使用add
函数将两个声音(或包络)相加。
1.2.4 滤波器
Nyquist自带了一些常见的内置滤波器。以下是一些更常见的滤波器:
(lp sound cutoff)
:低通滤波器(一阶巴特沃斯)。截止频率可以是浮点数或信号(用于时变滤波),单位为赫兹。(hp sound cutoff)
:高通滤波器(一阶巴特沃斯)。截止频率可以是浮点数或信号(用于时变滤波),单位为赫兹。(comb sound hz decay)
:将梳状滤波器应用于声音,增强(谐振)频率为hz
倍数的声音。(allpass sound decay hz)
:全通滤波器,创建延迟效果,无梳状滤波器的谐振。(notch2 sound hz)
:二阶陷波滤波器,中心频率为hz
。
1.2.5 声音变换与组合
在本入门教程中,无法详尽解释在Nyquist中变换声音的所有方法。这些函数不会直接修改声音,而是修改Nyquist环境。要使这些变化影响声音,必须使用cue
函数。
(scale factor (cue sound))
:将所提示声音的幅度按给定因子缩放。(load db (cue sound))
:将所提示声音的音量按给定的分贝数增加或减少。(at t (cue sound))
:在特定时间(秒)开始播放给定声音。这不能用于在开头或结尾添加静音,但可用于组合两个或更多声音。(seq (cue s1) (cue s2))
:创建声音s1
后跟声音s2
的序列。(sim (cue s1) (cue s2))
:组合两个声音,使其同时播放。
欲了解更多信息,请阅读《Nyquist参考手册》。
1.2.6 创建Nyquist插件
使用Nyquist为Audacity创建插件,就像创建一个扩展名为“.ny”并包含一些Nyquist代码的文本文件一样简单,添加一些注释以指明插件类型,然后将文件放在Audacity的插件目录中。以下是一个非常简单的插件示例:
;nyquist plug-in
;type process
;name "Simple..."
;action "Loading in..."
(mult (cue s) 0.5)
插件的前两行必须与上述示例完全一致,否则Audacity将无法加载(版本号用于支持未来的插件格式扩展)。接下来一行是插件类型,下面会讨论。然后是插件名称,即菜单中显示的名称,接着是“action”,这是Audacity在处理插件时显示的内容。还有其他可选行,后面跟一个分号“;”,分号内可包含Nyquist代码并将被执行。
Audacity支持三种可以用Nyquist编写的插件类型:
;type generate
;type process
;type analyze
这些类型对应可包含插件的三个菜单:生成、效果和分析。“生成”插件预期会全新生成音频。“效果”插件(“process”)会就地修改现有音频,“分析”插件会处理音频但不修改音频(尽管它们可以添加标签)。
对于“效果”和“分析”插件,Audacity会在Nyquist环境中设置好,以便用户选择的音频存储在变量s
中。插件文件中的所有表达式都会高效执行,最后一个表达式的返回值将替换Audacity中的所选内容。如果最后一个表达式不返回音频,Audacity将返回错误。
1.2.7 参数对话框
Audacity对插件显示对话框以从用户获取参数提供有限支持。以下是一个打开对话框的插件示例:
;nyquist plug-in
;type process
;name "Delay..."
;action "Processing Delay Effect by Roger Dannenberg.\nThis effect creates a fixed number of echos. ; (should be all on one line)
;info "Demo effect for Nyquist by Roger Dannenberg for Linux."
;control decay "Number of echos" int "times" 5 1 30
;control delay "Delay time" real "seconds" 0.5 0.0 3.0
(if (< count 0) (set
(load decay (at delay (delay s decay (- count 1))))))
当Audacity找到至少一个“control”行时,它会打开一个对话框,提示用户输入插件的某些参数。每个参数由一个文本框和一个滑块组成,用户输入每个参数后,最终值将存储在一个Nyquist变量中,变量名在“control”行中指定。以下是延迟效果对话框的外观:
注意“info”行显示在对话框顶部,“\n”会变成换行符。“control”行中的参数会影响参数的外观和限制。每个“control”行必须按顺序包含以下8个元素:
- “control”这个词
- 控件名称 - 这是用户操作对话框时将设置的Nyquist变量的名称。
- 控件左侧的标签
- 参数类型 -
int
(整数)或real
。 - 控件右侧值的标签(通常是像“Hz”或“dB”这样的单位)。
- 参数的默认/初始值
- 参数的最小值
- 参数的最大值
1.2.8 返回标签
Nyquist插件可以返回一个标签列表,而不是音频。标签列表只是一个(时间/标签)对的列表,例如:
((0.0 "start") (20.0 "midpoint") (60.0 "end"))
当插件返回这样一个列表时,Audacity会创建一个新的标签轨道,并在这些位置添加标签。这种类型的插件通常是“analyze”类型。
1.2.9 处理立体声轨道
Nyquist将立体声轨道表示为声音数组(不是列表)。许多Nyquist函数会自动处理这些数组,但并非所有函数都可以,所以有时你可能需要拆分数组或重新组合。以下是一些有用的函数:
(arrp s)
:如果s
是数组,则返回真(aref s 0)
:返回数组s
中的第一个元素 - 左声道(aref s 1)
:返回数组s
中的第二个元素 - 右声道(setf s (make-array 2))
:使s
成为长度为2的新数组(setf (aref s 0) left)
:使left
成为数组s
的第一个元素(setf (aref s 1) right)
:使right
成为数组s
的第二个元素
为方便起见,如果输入到Nyquist插件的是立体声,但你只输出单声道声音,Audacity会自动将其复制到左右声道。
1.3 参考资料
你可以在Audacity中找到一些示例插件,可将其作为起点进行检查或修改。学习Nyquist的最佳方法是实践。如果你在调试时遇到困难,可以考虑从卡内基梅隆大学计算机音乐项目 - 软件下载独立版本的Nyquist。
如果你在让Nyquist插件正常工作方面遇到问题,请将邮件发送至audacity-help@lists.sourceforge.net 。
如果你在Nyquist方面有创作的效果,欢迎加入audacity - users邮件列表与他人分享,或者如果你想讨论实现Nyquist特定功能的一般细节,也可以加入。
自2004年10月起,还有一个Audacity Nyquist邮件列表:audacity - nyquist@lists.sourceforge.net 。
别忘了查阅完整的《Nyquist参考手册》以及《Nyquist示例与教程》,以了解Nyquist工作原理的更多细节。
作者声明:本文用于记录和分享作者的学习心得,可能有部分文字或示例来自AI平台,如:豆包、DeepSeek(硅基流动)(注册链接)等,由于本人水平有限,难免存在表达错误,欢迎留言交流和指教!
Copyright © 2022~2025 All rights reserved.