SC:控制声音的元素,将音频写入文件

当讨论视觉艺术时,我们使用诸如颜色、形状、材质和亮度等术语来描述作品的性质。声音的性质同样可以被拆分为频率、振幅和音色,像我们在之前章节中讨论的。下文便是阐述如何在SC中控制这三个特性。

频率

运行下边这行代码。SinOsc.ar 产生频率为 500Hz 的正弦波。scope 信息 读取那个函数的结果并播放它。它同样会在一个新窗口内展示一个图示。波峰代表扬声器移出,波谷代表移入。图示中你看到的是扬声器移动的实际表述。当扬声器移动时,它们压缩并稀薄空气,从而创制声波。

//9.1. SinOsc
{SinOsc.ar([500, 500], 0, 0.4, 0)}.scope(2)

SinOsc.ar 的第一个引数是频率,设置为[500, 500],两个值的数组分别给左、右声道。把任意一个的值改为1000之后,你将会在图示中的那个声道看到更多的波。当然,你也会听到一个更高的音。

频率的音乐术语叫做音高。频率是造成C4与G6不同的原因。波越多意味着频率越高。

试着将频率(第一引数)在10 – 20000 间改变。声音会如何变化?什么频率范围,高还是低,你能听到吗?

如果你用10以下的值进行尝试会怎样呢?你将听不到任何声音,但在scope窗口内,你仍能看到扬声器的前后移动。当一个振荡器生成低于 25Hz 的波的时候,我们使用术语低频。这些低频振荡器(LFO)无法独立被听到,但却常常被当作patch的控制使用。我们稍后讨论这个问题。

振幅

我们可以使用同样的例子检验振幅。振幅的音乐术语叫做音量,或动态。频率在scope中由波的数量代表。而振幅则是由波的高度或大小来查看。较大的波意味着扬声器将前进和后退得更远,压缩更多的空气,这意味着更大的音量。

再次查看 SinOsc 的帮助文档。它的引数为:freq, phase, mul, add。我们使用 freq引数 改变频率。现在将用 mul引数 来改变振幅。为弄清楚这个引数是如何工作的,首先认识到 SinOsc 对象是通过以波的形状通过生成一连串数字创造正弦波。数字们从0偏移到1,然后降到-1,围绕中心值0震荡(就像两极)。学生们偶尔会混淆震荡范围(1到-1)和震荡的频率。他们是不同的。1 和 -1 是振荡器发生区间内的数字。500是在这些值间移动的快慢。如果我们在波(因此也是扬声器)的位置进行一个快照,我们将会看到这些数字:[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0, -0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0] 等等。这些数字可以被任何种类的数学函数操作:加、减、乘、除等等。引数mul 用mul的值缩放或乘以这些数字。如果我们将 mul 改变到,比如说,0.5,那么所有值都将被减半。因此,[0, .1, .2, .3, .4, ] 等将变为 [0, .05, .1, .15, .2, ] 直至0.5,然后又下降。下例我们将由1开始,这也是系统能处理的最大振幅。在测试这个例子前,请调小你电脑扬声器的音量,或摘除你的耳机。

//9.2. 使用mul的振幅
{SinOsc.ar(500, 0, 1.0)}.scope(1)

停止声音(command+句号键),并尝试将 mul 的值在0.1和0.9之间改变,再听。波的大小将改变,响应振幅。输入大于1的值是可能的,但这已超越了比特深度的能力,并会令声波失真。大于1的值对音量来说太高了,但却在其他环境下很有用,稍后可见。下边的SC范例图示了输出的饱和、修剪(clip,波的顶端被修剪)或失真。

//9.3. 失真
{SinOsc.ar(500, 0, 2.0)}.scope(1)

有你需要波被修剪的情形,但有比往振幅上加过多的值来做到。在模拟工作室里,你有可能会毁坏设备。在数码王国,没那么危险(你不可能破坏程序),但你危害(compromise)了声音。更重要的是,用超大值做修剪技术含量太低,并泄漏了你经验的缺乏。被修剪的信号会揭示真相。

周期,形状和音色

下例展示了一个我们并不将之视为调的声源。

//9.4. 噪音
{WhteNoise.ar(0.7)}.scope(1)

我们没听到音的原因是没有模式(至少在我们能认知的一个时间范围内)可言。上边的正弦波从0到1到0到-1到0平滑移动并重复这个动作。一条具备任何类型重复模式的任意形状或轮廓的波都是周期性的。周期波听起来像音。沿着模式进行的每次循环被称作一个周期、波或循环。一个没有模式的声音被称为非周期性的,并不会被听作音。这些术语不是绝对的。也就是说,一个波可以有更强或更弱的周期性。模式或周期越清晰,音越清晰。

频率即音,波的大小是振幅或音量,波形是音色。我们稍后将讨论不同的波形是如何产生的,但现在要知道不同形状的波产生不同的音色。总体来说,方向急剧改变的波有更亮的音色。

以下是这些波的音频等价物。用鼠标从上到下移动收听不同的波。它们依次是:正弦波,锯齿波,脉冲,赛较薄,低频噪音,“灰尘(dust)”,粉噪音和白噪音。拖拽边角以改变scope窗口的大小。

//9.5. 波形
(
{Out.ar(0, In.ar(MouseY.kr(15, 23).div(1), 1)*0.8)}.scope;
{Out.ar(16, [SinOsc.ar, Saw.ar, Pulse.ar,
      LFTri.ar, LFNoise0.ar(200), LFNoise1.ar(200), Dust.ar(100),
      PinkNoise.ar, WhiteNoise.ar])}.play
)

下边是它们的图示:

各种波形的plot
各种波形的plot

前四个的区别应该很容易听出来,噪音的例子就不那么明显了。那是因为模式更不清晰。不同的波形改变音色,但它们同样可被用作 LFO 控制,即,塑造其他一些参数。在这些情况下,知道每条波的形状便很有重要,因为被控制的参数(比如频率)将继承那个形状。

这里是相同的例子,除了每个波形都被用于一项控制。再次,上下移动鼠标去听每条波。但这样,第一个 SinOsc 生成我们听到的音。其余的则控制那个 SinOsc 的音,因此我们听到的是伴随每个波形的音。我们将随后更深入的研究控制。

//9.6. 波形做控制
(
{Out.ar(0, In.ar(MouseY.kr(15, 20).div(1), 1)*0.8)}.play;
{Out.ar(16, SinOsc.ar([SinOsc.ar(2), LFSaw.kr(2), LFPulse.kr(2),
      LFTri.ar(2), LFNoise0.ar(2), LFNoise1.ar(2)] * 100 + 500))}.play
)

正弦波,三角波,锯齿波和脉冲波的波形很清晰。LFNoise0LFNoise1 是随机(非周期性的)的波。LFNoise0 生成离散的阶梯值。LFNoise1 生成以内插值替换的(interpolated),或斜坡(ramped)值。以下是两者的图示。

LFNoise0 和 LFNoise1 的差别
LFNoise0 和 LFNoise1 的差别

相位

在绝大多数情况下,相位的改变并不影响音质,但对于立即音色、相位删除,以及相长或相消干涉的工作方式来说,相位是一个重要的概念。以下是我们的第一个例子。

//9.7. 相位
{SinOsc.ar(500, 0, 0.7)}.plot

上例中,我们使用 plot消息。这将不仅会播放声音,而且会绘制出波在第1/100秒时的图形。第二引数(0)是相位。常识将这个引数的值换为0.785, 然后 1.57, 然后 2.355 并最后到 3.14。为什么这些数字重要?因为它们是π(pi,圆周率)的倍数。波的图会从它循环的响应点开始。3.14是循环的一半,2*pi 是一个完整的循环。SC3 理解 pi。相位常常被表述为度。0 是 0度,0.5pi 是 90度,pi 是 180度,以此类推。

//9.8. 相位们
{SinOsc.ar(100, [0, 0.5pi, pi, 1.5pi, 2pi])}.plot

相位直接影响合成的两个方面:两段波的干涉(当它们处于不同相位)方式,以及控制波与目标波互动的方式。

要图示上边第二点,我将跳到用正弦波做控制的一个例子(后边将详述)。下一个例子中的第二个 SinOsc 正控制着第一个 SinOsc 的音高(从MIDI转化)。以简单的术语来说,正弦波的形状被由F4到G5依附到一个虚拟琴键上:就像波上下移动那样扫过琴键。但就像你听到的那样,第一个例子并未并未由F4开始,而是由C4开始,中间的音。那是因为正弦波从0开始,然后移高到1,下到-1,如此往复。当相位的引数被改变到0.5pi,曲子将由其波峰开始,因此是F4的顶端,G5范畴。如果设置到 1pi,曲子将由循环的半程开始,也就是0,随后继续下降。1.5pi 将由波谷开始。运行第一行看所有行的plot线,然后以此逐行运行并仔细聆听起始音。

//9.9.     你可以听到的相位 (作为控制)
// 全部相位: 0, .5, 1, 1.5
{SinOsc.ar(400, [0, 0.5pi, pi, 1.5pi])}.plot;
// 0 相位
{SinOsc.ar(SinOsc.ar(0.3, 0, 7, 72).round(1).midicps, 0, 0.7)}.play
// 0.5pi (1/4) 相位
{SinOsc.ar(SinOsc.ar(0.3, 0.5pi, 7, 72).round(1).midicps, 0, 0.7)}.play
// 1pi (1/2) 相位
{SinOsc.ar(SinOsc.ar(0.3, 1pi, 7, 72).round(1).midicps, 0, 0.7)}.play
// 1.5pi (3/4) 相位
{SinOsc.ar(SinOsc.ar(0.3, 1.5pi, 7, 72).round(1).midicps, 0, 0.7)}.play

录入(写入一个文件)

这段文字的前半部分聚焦于合成,使用SC进行实验。SC可以使用MIDI或patch的集合组织和演绎整个作品。它通过将命令发送至伺服器做到这点。实际上这些工具是革命性的并将改变(恕我直言)我们创作电子音乐的方式。但现在我们要了解的是传统的方式,由模拟合成器创造的声音被录制用作原料,像一个给作曲拼贴用的调色盘。在这样的模式下,正式的作曲在(收集完声音之后)数字音频工作站中稍后发生。因为在第一部分中,我们的目标是用patch产生足够有趣的声音,录下它们能然后将它们导入一个数码编辑器,类似 ProTools, Amadeus, 或 Logic,并在那里组织声音。

在每个伺服器窗口上,都有一个控制准备录音、录音和停止的按键。依次按下的话:打开一个将要录入的文件,然后录入到那个文件,然后停止录入。录音的默认值是44.1k,32bit,立体声,自动生成独特的文件名,文件位于SC文件夹下的recordings文件夹。那个文件可以被导入数字编辑器并被用于创作。

我发现导入 32bit 文件到其它软件是一个问题,因此我将默认值改到16。你可以在源文件 Server.sc 里做这一改变,但由于我总在不同的机器间转悠,因此一个命令行对我来说更省事。一开始,在启动伺服器的时候便可这么写:

Server.default = s = Server.internal.boot; s.recSampleFormat = "int16";

我同样喜欢在录音前命名我的文件,我同样用命令行来做这个事。以下是用命令行来设置默认值,声道数,文件名以及开启、停止录音。这些命令行可被用于替代伺服器上的录音按钮。

//9.10. 录音比特深度、音轨、文件
Server.internal.recSampleFormat = "int16"; // 或者 Server.local
Server.internal.recChannels = 1; // 单声道
// 在SC文件夹内保存文件, 如果重复将被覆盖
Server.internal.prepareForRecord("audio1.aif");
// 或保存在SC文件夹下的recordings文件夹内
Server.internal.prepareForRecord("recordings/audio1.aif");
// 或保存在Music文件夹下 (将students换为你的文件名)
Server.internal.prepareForRecord("/Users/students/Music/audio1.aif");
// 然后录音, 别用按钮,用下边的代码.
// 但运行前先运行一个之前的例子
// 这样你才有录的东西

Server.internal.record;

// 然后
Server.internal.stopRecording;

但是,录音按钮在当你在实验一个patch然后突然出现某些有趣的东西时很方便:仅仅按下按钮,然后你很酷的声音便被保存下来。你可以在你运行一个patch之前或之后开启录音功能。你可以在录音的过程中加入更多patch。

练习 / 趣味

电子音乐对我来说始终是有趣的。我希望这份文本有教育意义和有用,但我同样希望挖掘你自我发现的冒险精神。为了这个目的,每章我都以一个实际应用的例子结束。代码将会更复杂,可能超出我们当前学到的东西,但我的意图不是直接的教育。这些例子们在更大程度上是数码合成应当是的样子:探索新声音。你可以忽略我们没有讨论过的部分或查阅帮助文档。

当你偶然发现一些有趣的东西时,有两个方式可以保存这些声音。第一是将那个patch保存为独立的文件。方法我就不翻译了。很简单。

下边的patch用三个ugen生成声音:一个 LFNoise1, 一个 SinOsc 以及一个 LFSaw。它们被以一个相当复杂的方式连接。你可以按你的意愿实验,改变每个引数的值,但移动的范围应大于最大漫游范围。但最大延迟应始终大于实际延迟。衰减时间是回声共鸣的长短。我已标准你可以尝试的值。第二个patch发起五条正弦波,它们仅区别于声相位置和相位(以说明相位)。最后一条表明了频率、振幅和音色的改变,因为这是我们刚刚教授的内容。

玩得开心。

// 9.11. 漫游正弦, 随机正弦, 三维
(
    // 双击上边的括号以迅速选中整段代码
    // 或使用组合键 com-shift-b
{
var out, delay;
out = SinOsc.ar( //正弦波振荡器
    abs( //这可以避免出现负值
           LFNoise1.kr(
                   0.5, // 总体漫游频率
                   600, // 总体漫游范围
                   LFSaw.kr(
                           1.5, // 独立移动的速度
                           mul: 50, // 移动的深度
                           add: 500 // 移动的范围
                    )
              )
    ),
    0,
    0.1 // 音量,保持低于0.2
);
//延迟
delay = CombN.ar(out,
    3.0, // 最大延迟
    [1.35, 0.7], // 实际延迟,保持低于最大延迟
    6 // 延迟衰减
);
Pan2.ar(out, 0) + delay
}.play
)

第二个patch。你可以同时运行它们。或者运行同一patch的多个实例。

( // <->
// 这个patch控制声音的三维: 音调, 振幅, 和音色。
(
{
var trig, out, delay;
trig = Impulse.kr(6); // 触发率
out = Blip.ar(
     TRand.kr(48, 72, trig).midicps, // 音调MIDI范围
     TRand.kr(1, 12, trig), // 音色范围
     max(0, TRand.kr(-0.5, 0.4, trig)) // 振幅
);
out = Pan2.ar(out, TRand.kr(-1.0, 1.0, trig));
out = out*EnvGen.kr(Env.perc(0, 1), trig);
out = Mix.ar({out}.dup(6))*0.2;
delay = CombL.ar(out, 2.0, 4/6, 6);
out + delay
}.play
)

OK, 再来两个; 第一例用Saw做控制 (注意上升的声音)。第二例则展示了Dust如何被用来触发事件。

(
{
Mix.ar(
      Array.fill(5, // 振荡器数量
            {arg c;
                 Pan2.ar(SinOsc.ar( // 确保add大于mul
                        LFSaw.ar((c*0.2 + 1)/3, mul: 500, add: 700)
                  ), LFNoise0.kr(1)) // 声相速度
             }
       )
)*0.1
}.play
)
(
{
Mix.ar(
       {Pan2.ar(
             Klank.ar(
                     `[Array.fill(3, {exprand(1000, 10000)}),
                      1, Array.fill(3, {rrand(1.0, 4.0)})],
                      Dust.ar(1/3, 0.1)),
              LFTri.kr(rrand(3.0, 10.0)))}.dup(20)
) }.play;
)
Be Sociable, Share!

作者: ww1way

http://about.me/ww1way

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.