SuperCollider:加减合成

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]


scope
scope

部件产生器(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中,有许多处理数据数组的方法,我们将随着课程的进行一一对它们进行探讨。

Be Sociable, Share!

2 thoughts on “SuperCollider:加减合成”

  1. 谢谢这么详细的解释,很有用。最近在上这门课,本来因为没有任何coding的基础很纠结。。。

    Reply

    ww1way Reply:

    :)

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *