Pyo文档(一)
作者是Olivier Bélanger,自ajaxsoundstudio.com; 黄复雄编译,有意译和少量省略。
本文对应于原文档的Parts of the documentation部分,但不包括其中的API documentation部分;API documentation将以专文处理。
关于Pyo#
Pyo是用C写成的Python模块,用于生成数字信号处理(DSP)脚本。它提供一整套的类,用于构建音频软件,编写算法音乐,或通过一种简单、成熟、强大的编程语言随意探索音频处理。
它包含众多的声音信号处理类。用户可以用它在Python脚本、工程中直接加入信号处理链,并可通过解释器实时操控处理链。Pyo模块中的工具提供最基本的东西,如音频信号的数学运算,基本的信号处理(滤波器、延迟器、合称发生器,等等),也提供复杂算法以生成音频颗粒(sound granulation),以及别的生成音频的操作。Pyo支持开放声音控制协议(OSC, Open Sound Control),以便软件间的通信;支持MIDI协议,以生成声音事件,控制参数的处理。Pyo能够利用一种成熟、广泛使用的通用处理语言的诸多优势,生成复杂的信号处理链条。
Pyo的开发者是Olivier Bélanger <belangeo@gmail.com>。
要提问与评论,请订阅pyo-discuss的邮件列表。
报告错误或请求新特性,请使用github库的issues tracker。
源文件和二进制文件可在这里下载:http://ajaxsoundstudio.com/software/pyo/
下载安装文件#
安装文件可用于Windows(XP/Vista/7/8/10)和MacOS(from 10.6 to 10.12)。
要下载最新的Pyo编译版,请到Pyo的页面。
在Debian和Fedora发布版中,你可以从包管理器中得到Pyo。Pyo库名是python-pyo或python2-pyo,对应Python 2.7;或是python3-pyo,对应Python 3.5+。
如果你用的是Arch linux,包名是python2-pyo,还没有对应Python 3.5+的包。
安装文件的内容#
安装文件将向系统安装两个不同的软件。其一是安装Pyo模块(包含单精度/32位和双精度/64位两套编译),及其在当前Python发布版下依赖。其二是安装E-Pyo,一个简单的文本编辑器,做了特意调校,以便于编辑、运行音频Python脚本。
Pyo是一个Python模块...#
这意味着系统里先要有Python(2.7, 3.5或3.6(推荐))。如果没有安装Python,可以到这里下载python.org。
Pyo也提供一些GUI工具,以控制音频处理,或使其视觉化。如果想使用所有Pyo的GUI特性,你必须安装WxPython 3.0 (classic版对应python 2.7,phoenix版对应python 3.5+),这里能得到:wxpython.org。
库的结构#
下图表示库的内部结构。
起步#
启动服务器,输出声音#
生成并引导Pyo服务器(可配置采样率、声道数量等)。启动Pyo服务器,即开启音频和MIDI接口,以备接收其他Pyo对象生成的音频和MIDI。
1 2 3 |
|
生成并输出音频。下例是生成正弦振荡器对象,并输出到服务器。这时你就能听到声音了。
1 |
|
停止服务器:
1 |
|
服务器的图形界面#
如果不是在交互解释器中执行上述代码,而是非交互地执行脚本文件,那么还需要加上图形控制界面,以免脚本瞬间执行完毕,导致你听不到声音;使用交互解释器时也可以生成图形控制界面。
1 |
|
也可以通过Python的time
模块控制服务器关闭时间:
1 2 |
|
调整对象参数#
振荡器对象可以随时调整参数。或通过set方法:
1 |
|
或直接赋值:
1 |
|
对象的链条与封包#
一个振荡器实例可以作其他实例的输入,从而构成对象实例链条。下例是把前一个实例的频率传给后一个实例。
1 2 3 4 5 |
|
也可以为振荡器生成一个封包:
1 2 3 4 5 6 |
|
所有类都有示例#
Pyo中的所有类都带着一个示例,以展示类的用法。比如Harmonizer
类,可以这样执行他的示例:
1 2 |
|
配置音频输出(特别是在Windows系统中)#
以下提示有助于你在Windows上配置音频输入/输出。其中一些处理程序也适用于其他操作系统。
在Windows中检测、选择音频宿主API#
在Windows中选择合适的音频API是件头疼的事。你可以使用Pyo官方的检测脚本检测你的系统,以确定:
- Pyo是否可以双工模式运行,即输入、输出都可用。
- Pyo是否能连接到Windows中可用的不同宿主API。
调校Windows的WASAPI驱动#
Windows的音频会话API(WASAPI, Audio Session API)是微软最现代的与音频设备对话的方法,自Vista以后可用。Pyo默认宿主是DIRECTSOUND,但你可以换成WASAPI:更换服务器对象的winhost参数。如果上述检测脚本告诉你:
1 |
|
那么在任务栏上的扬声器图标上点右键,点选“播放设备”。然后选择你的设备,点击“属性”按钮;在“高级”书签页,确认其采样率与Pyo的采样率(默认为44100Hz)相同。如果需要,还可以勾选“独占模式”中的选项,这样可以忽视系统的混音器、缺省设置、尤其是音频驱动提供的任何效果。
假如获得如下信息,又想让Pyo以使用双工模式运行的话,那么在“录音设备”选项中也做同样的操作:
1 2 |
|
如果你用的是比较便宜的声卡(特别是,内置声卡都很不好!),你可能需要加大Pyo服务器的缓冲区规模,以避免音频流故障。
服务器初始化样例#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
选择指定设备#
一个宿主API可以指向多个可用的设备。有几个有用的函数可以帮助你选择音频设备:
- pa_list_host_apis(): 打印音频宿主API列表。
- pa_list_devices(): 打印音频设备列表。如果有设备索引号,那么在第一列。
- pa_get_default_input(): 返回默认输入设备索引号。
- pa_get_default_output(): 返回默认输出设备索引号。
- pa_get_default_devices_from_host(host): 为给定音频宿主返回默认输入、输出设备。
运行下面的代码,看看你的音频配置的当前状态:
1 2 3 4 5 6 |
|
如果意向宿主的默认设备不是你想要的,你可以用setInputDevice(x)
和setOutputDevice(x)
两个方法,通知服务器哪个设备是你想要的。这两个方法接收意向设备的索引号,必须在服务器引导(Server.boot()
)前调用。比如:
1 2 3 4 |
|
提高Pyo程序的性能#
这里列出多个提示,帮助你提供Pyo程序的性能。
Python提示#
大部分计算都是在Pyo的C语言部分进行的,所以Python层面能做的不多。不过仍有两个技巧可以考虑:
调整解释器的检查间隔#
用sys.setcheckinterval(interval)
调整解释器的检查频率。默认值是100,即每100条Python虚拟指令执行一次检查。加大此值可能会提高使用线程的程序的性能。
使用subprocess
(子进程)或multiprocessing
(多进程)模块#
使用subprocess
或multiprocessing
模块能在多处理器上批量处理。下面的小例子使用了multiprocessing
模块,以便在多处理器上批量进行正弦(Sine)波计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
避免在初始化之后进行内存分配#
动态内存分配(malloc/calloc/realloc)容易引起不确定性;分配内存的时间无法预见,使其不适合于实时系统。为了保证音频回调函数何时候都能平稳运行,最好在程序初始化时生成所有音频对象,然后在需要时调用它们的'stop()``play()``out()
方法。
注意,一个简单的算数符号与音频对象关联后即可生成一个傀儡对象(以持有变动后的符号),于是会分配内存给它的音频流并且增加一个处理任务到CPU中。运行下面的简单代码,观察其进程的CPU如何增长:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
这个程序的高效版本应该像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
别做任何会激发垃圾回收的事#
Python的垃圾回收也是一个不确定的进程。你要避免任何会激发它的事。所以,不要删除音频对象——这最终会删除许多音频流对象,而应该只是调用它的stop()
方法以便把它从服务器的处理循环中移除。
Pyo提示#
在应用效果前先混合#
使用Pyo很容易使CPU超饱和,尤其是使用多声道扩展特征时。如果你的最终输出使用的声道少于对象中的音频流数量,别忘了先混合(调用它的mix()
方法),然后再给信号总体应用效果。
看看下面的片段,它生成50个振荡器构成的的一个合奏,再对最终声音应用一个相位效果。
1 2 3 4 |
|
这个版本在Pyo作者的i5 3320M @ 2.6GHz的ThinkPad T430上试用约47%的CPU。问题在于50个振荡器给Phaser对象作为输入,生成50个一样的Phaser对象实例,每个对象实例一个振荡器。这将大大地浪费CPU。下面的版本混合所有振荡器为一个立体声流,然后再应用效果,这样CPU消耗降到约7%!
1 2 3 4 |
|
当用到高消耗效果时,这会剧烈影响CPU的消耗。
停止不用的音频对象#
当你不用一个音频对象(但还想留着备用)时,调用stop()
方法。这会通知服务器把它移出计算循环。设置音量为0不能节省CPU(全都计算完后乘以0),而stop()
方法可以。Pyo作者本人的合成类常常近似如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
控制属性当用数字而不是Pyo对象#
当纯数字用作属性时,对象的内部处理函数会进行优化。除非你真地需要通过某些参数控制音频,否则不要浪费CPU的时钟周期,而是把固定数值给到所有属性,这样它们就不需要随时间变更。看下面的对比:
1 2 3 4 5 6 7 8 9 |
|
生成p2
的spread
属性时用一个音频信号,导致48个槽口(notch)的频率在每次采样时都要重新计算,这将是消耗很高的进程。
检查非常态数/低常态数/非规格化浮点数(denormal/subnormal number)#
据维基百科:
在计算机科学的浮点数算法中,denormal数或denormalized数(现常作subnormal数)会填充0后面的潜流(underflow)1空位。任何非零的数,数值小于最小常态(normal)数时,即为subnormal数。
问题在于,某些处理器计算非常态数值时很慢,这会很快地增加CPU消耗。解决办法是用一个Denorm
(非常态)对象掩护(wrap)将受制于非常态数的对象(任何内部带有递归延迟行的对象,比如过滤/filter, 延迟/delay, 混响/reverb, 泛音/harmonizer,等等)。 Denorm
添加一点点噪音到自己的输入中, 仅是略大于最小常态数的量。当然,你可以把相同的噪音用于多重的非常态化:
1 2 3 4 5 |
|
使用Pyo对象(PyoObject),只要可用#
如果Pyo对象能实现你的意图,优先找来用,它一定比你从新写的更高效。下面的结构尽管在教学上有价值,但效率(即CPU与内存消耗)永远比不上用C写的Pyo对象(Phaser)。
1 2 3 4 5 6 7 8 |
|
使用Biquadx(stages=4)
也会比用相同参数串联四个Biquad
对象更高效。
避免三角函数计算#
避免音频频率的三角函数计算(Sin
, Cos
, Tan
, Atan2
, 等等), 而用简单的近似对象代替。比如,你可以用基于Sqrt
的更廉价的对象代替纯Sin/Cos
声像函数:
1 2 3 4 5 6 7 8 9 10 11 |
|
使用近似对象,如果绝对精确没有必要#
绝对精确不是确实重要时,你可以通过近似对象节省宝贵的CPU时钟周期。FastSine
是sin
函数的近似对象,它几乎比查表(Sine)廉价一半。Pyo作者计划将来添加更多的近似对象。
重用你的生成器#
有时有可能把相同的信号用于近似目的。琢磨下面的过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
在这里,同一个白噪音同时用于三个目标。首先,用于生成非常态信号。然后,用于生成小震动以备波导用作频率(给线性声音添加一个小嗡嗡声)。最后,用作波导的激励。这无疑比生成没有明显听觉差异的三个不同白噪音要廉价。
任由mul
和add
属性保持默认值,只要可能#
当mul=1
和add=0
时,有一个内在条件会绕开对象的“后置处理”(post-processing)函数。好的实践是在同一处使用多重控制,而不是乱糟糟地在每个对象中使用mul
属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
避免图形更新#
即使运行在不同线程中,用不同的属性,音频回调函数与Python程序图形界面都是同一个进程,分享相同的CPU。如果你不需要看表或使用滑块,那么不要使用服务器的GUI。你可以从命令行启动脚本,带上旗标-i
以便解释器保持活动。
1 |
|
CPU高消耗对象#
这是库中的大部分、但并非完全的CPU高消耗对象的列表。
- Analysis
- Yin
- Centroid
- Spectrum
- Scope
- Arithmetic
- Sin
- Cos
- Tan
- Tanh
- Atan2
- Dynamic
- Compress
- Gate
- Special Effects
- Convolve
- Prefix Expression Evaluator
- Expr
- Filters
- Phaser
- Vocoder
- IRWinSinc
- IRAverage
- IRPulse
- IRFM
- Fast Fourier Transform
- CvlVerb
- Phase Vocoder
- Almost every objects!
- Signal Generators
- LFO
- Matrix Processing
- MatrixMorph
- Table Processing
- Granulator
- Granule
- Particule
- OscBank
- Utilities
- Resample
-
译注:因精度限制/指数不够用而在小数点后加0表示,如0.000123e-126。这样一来,后面的有实际意义的数值即成为潜流(underflow)被丢弃,从而影响结果;如果重复此类计算则可能导致严重错误。 ↩