SuperCollider中的声音合成
(注意声音一开始将是单声道的,在左声道。之后我们将挑选出立体声位置)。
我们将在这个教程内使用内部服务器(internal Server)。这将允许我们获得我们合成的声音的示波器(oscilloscope)视角,它将协助阐述一些概念。
Server.default=s=Server.internal; s.boot;
出于方便考虑,我们将使用一个特定的便捷结构(shortcut construction)来练习声音合成。稍后我们将看到完成这个东西的另一种方式,那是更被推荐的方法,但我们将从下边的方法开始,因为这可以在目前避免一些问题,并允许我们一直向前走。
这个结构看起来像下边这样,但不要尝试运行这个代码:
{ // 一些合成代码 }.scope
// 这使用了Lance Putnam的频率范围. // 我将在后台持续运行它以绘制我们探索的声音的光谱 FreqScope.new // 要自行使用它你不得不先下载它 // 但这份教程没有它依然可以运行.
[注意:SwingOSC或Windows(PsyCollider) 用户应将下边代码中的.scope修改为.jscope。你们无需使用内部服务器。你们同样可以运行JFreqScope.new]

部件产生器(Unit Generator)
SuperCollider遵循部件产生器范例(Unit Generator paradigm),这种范例同样运用于其它合成语言,诸如Csound, Max/MSP, PD, Reaktor等。
它有许多基元建立块(primitive building blocks),例如音调产生器、滤波器或空间器(spatialiser),它们是部件产生器。它们在一个处理图表(processing graph)中被串联在一起,以制造更复杂的合成器和声音处理器。这些基元也被称为UGen。
每个UGen都有一些输入和输出的设置。绝大多数UGen仅有一个输出,一个音频流或者几类控制信号。输入依各UGen的功能而各不相同。
在学习不同UGen的过程中,你将慢慢习惯于作为输入和输出的典型参数值。
编程“连接”有特定的方法,这属于SuperCollider语言语法的一部分,在你学习的过程中,你还将慢慢熟悉各部件的名称。
减法合成(Subtractive Synthesis)
这是开始学习SuperCollider的一个好方法。
在减法合成中,我们从一个复杂的音源开始,然后从这个音源里删减一些部分以获得一个更具可塑性的声音。这也被归类于source+filter模型中。
// 这行代码将制造一个纯白噪音音源 // 在整个频谱范围内能量均衡 // 这并不是一个令人愉快的声音 // 参数0.1确保它不会太大声,但还请谨慎运行 {WhiteNoise.ar(0.1)}.scope
这仅是单独的音源。现在我不得不用滤波器处理出一个不那么粗糙的声音。
{LPF.ar(WhiteNoise.ar(0.1),1000)}.scope
LPF是一个低通滤波器,它会滤除高于它截止频率的声音的能量,在本例中这个截止频率是1000Hz。
在SuperCollider中,将白噪音生成器WhiteNoise插入滤波器LPF中,我将它们嵌套了起来。你可以将一个UGen的输入想象为在圆括号内的一串端口。
LPF.ar(输入信号, 截止频率, ... )
在上例中,“输入信号”是一个白噪音音源,因此那是WhiteNoise生成器的归所。截止频率是一个固定的数字,1000,第二个引数。
如果说我们现在想要一个依时间变换的截止频率。我们可以使用线性生成器,Line:
Line.kr(10000,1000,10) // 10秒从10000降到1000
因此,Line UGen替代了固定值1000的位置:
{LPF.ar(WhiteNoise.ar(0.1),Line.kr(10000,1000,10))}.scope
SC中有许多可用的音源以及很多的滤波器(试试它们的帮助文档)。
将一个音源插入一个滤波器的例子:
{Resonz.ar(LFNoise0.ar(400),1000,0.1)}.scope
我们再次使用Line生成器来不断改变滤波器的中心频率。
{Resonz.ar(LFNoise0.ar(400),Line.kr(10000,1000,10),0.1)}.scope
一个更直观整洁的方式来写上边的代码(我们将回到这个公式)
( { var source, line, filter; source=LFNoise0.ar(400); line=Line.kr(10000,1000,10); filter=Resonz.ar(source,line,0.1); // 最后一个东西是从尖括号的函数返回的 // 比如说,这是我们最后听到的声音 filter }.scope; )
加法合成(Additive Synthesis)
相比从复杂的东西开始以及拿走能量来塑造声音,我们可以从相加很多简单建立的块来创造更复杂的声音。
在电脑音乐中,最经典的建立块(building blocks)是正弦音。
{SinOsc.ar}.scope // 默认为一个和音A (440Hz)
这是一次性得到两个正弦音的方法:
{SinOsc.ar(400,0,0.1) + SinOsc.ar(660,0,0.1)}.scope
这是一个简单得多的方式:
{SinOsc.ar([400,660],0,0.1)}.scope
一些奇特的事将发生在立体声领域,我一会介绍。
让我们首先介绍一个声相UGen。
Pan2.ar(输入信号, 声相位置)
声相位置从-1 (最左)到1 (最右)
{Pan2.ar(WhiteNoise.ar(0.1), MouseX.kr(-1,1))}.scope
因此,声相器接收一个单声道信号,并将之放到立体声领域。
现在,多声道声音在SuperCollider中能被很直接的生成,只需使用一个数组。
我们将在之后的课程中详述数组,现在你只需将它们设想为一串数据。
[100,200,300,400,500] // 一个序列中有五个数字
序列中每个连续的元素将被置于一个声道:
{SinOsc.ar([400],0,0.1)}.scope // 单声道声音 (看观察仪)
{SinOsc.ar(400,0,0.1)}.scope // 同样是单声道声音——一个数字无须使用方括号
{SinOsc.ar([400,660],0,0.1)}.scope // 双声道声音 (看观察仪)
{SinOsc.ar([400,660,870],0,0.1)}.scope // 三声道声音——你可能只能听到两个,因为你电脑的输出设备也许仅是双声道的。
你需要一个将多声道声音转换为单声道或双声道信号的方式。
一个解决方法是用Mix UGen将多声道声音包裹起来:
{Mix(SinOsc.ar([400,660, 870],0,0.1))}.scope // 通过Mix将双声道转为单声道
接下来,当然,Pan2允许我将这个放到立体声领域:
{Pan2.ar(Mix(SinOsc.ar([400,660],0,0.1)),MouseX.kr(-1,1))}.scope //将单声道重新转为立体声
在加法合成中,如果我们知道一个声音波谱(频率内容)的构成,我们就可以通过为每个组件频率增加正弦波来合成它。
// 这是一个小三钟(minor third bell)的波谱构成 // 基础频率为500 // 跑一下这个程序,然后在post窗口看看乘法器是如何工作的 500*[0.5,1,1.19,1.56,2,2.51,2.66,3.01,4.1]
// 钟的波谱,每一部分的音量相等 {Mix(SinOsc.ar(500*[0.5,1,1.19,1.56,2,2.51,2.66,3.01,4.1],0,0.1))}.scope
我同样可以在mix中给每个部分专属的振幅,而不是让它们都默认为0.1。
// 钟的波谱,每一部分的音量不同 {Mix(SinOsc.ar(500*[0.5,1,1.19,1.56,2,2.51,2.66,3.01,4.1],0,0.1*[0.25,1,0.8,0.5,0.9,0.4,0.3,0.6,0.1]))}.scope
这是一个普遍性的patch,引入变量n来表述希望使用的正弦音数量:
( var n; n=10; {Mix(SinOsc.ar(250*(1..n),0,1/n))}.scope; )
如果你不清楚一段代码里的一些东西是什么,单独研究它:
(1..10) // 运行这一行,然后在post窗口看看出现了什么
在SuperCollider中,有许多处理数据数组的方法,我们将随着课程的进行一一对它们进行探讨。
谢谢这么详细的解释,很有用。最近在上这门课,本来因为没有任何coding的基础很纠结。。。
Reply
ww1way Reply:
10月 15th, 2016 at 16:49
:)
Reply