SuperCollider学习笔记(一)- 振荡器(Oscillators)

18 篇文章 1 订阅
4 篇文章 1 订阅

前言

作为计算机作曲语言 MUSIC-N 大家族的一员,SuperCollider 这个编程语言为实时声音合成和算法作曲提供了很好的解决方案,它不仅功能全面,版本新,还有十分好用的官方IDE - SuperCollider IDE,其提供的代码联想、高亮和调试功能为编程开发带来了很多的便利。考虑到 SuperCollider 的使用人群比较少,很难找到中文版的学习资料,作为计算机编曲的初学者,我将自己学习过程中的笔记和思路整理的这系列文章中,希望能对大家有所帮助,在此真诚感谢大家阅读,并欢迎交流指正。

对摇滚史密斯和独立电子感兴趣的朋友们,欢迎关注鄙人B站主页,感谢大家支持!

定义

电子振荡器(Electric Oscillator)原本是指用来产生具有周期性的模拟信号的电子电路,在SuperCollider语言中是单元生成器(Unit Generator)的抽象类 UGen 的一个子类,用于生成正弦波、方波、锯齿波等,是产生音乐的一个关键类,下面我以 SuperCollider 的官方教程 Tour of UGens 为思路来分别解释典型振荡器的使用方法

分类解读

LF - 低频振荡器 (“Low Frequency” Unit Generators)

低频振荡器产生的频率通常低于20Hz,故我们通常是听不到的,可以用于制造颤音等效果。注意:低频振荡器产生的信号没有频带限制(non-band-limited),故可能产生混叠(Aliasing)现象 。

LFPar, LFCub, LFTri, Impulse, LFSaw, LFPulse, VarSaw, SyncSaw 这些函数有共同的参数:frequency(频率)、phase(相位)、mul(振幅的乘数,介于0到1的数,输出是原值与它相乘)和add(上下位移):

  • LFPar 可以产生两个抛物线(parabola)组成的正弦样式的信号,在 SuperCollider IDE 中可以通过scope函数来查看波形,因为使用的是ar函数(Audio Rate)故若频率在人耳听力区间中的时候同时可以听到输出的声音:
{ LFPar.ar(8, 0, 1) }.scope(1, zoom: 4); // 频率为8,相位是0,振幅不改变,但是由于频率太小导致曲线形状无法辨识
{ LFPar.ar(800, 0, 0.1)}.scope(1, zoom: 4);
 // 频率是800,故能听到声音,振幅变为十分之一

{ LFPar.ar(LFPar.kr(0.2, 0, 400, 800), 0, 0.1)}.scope(1, zoom: 4); // 用LFPar产生的control rate来实现频率的变化
  • LFCub 是产生两个三次曲线(cubic curve)来组成的正弦样式的信号,同样通过scope函数来查看波形:
{ LFCub.ar(800, 0, 0.1) }.scope(1, zoom: 4); // 频率为800,相位0,振幅为十分之一
{ LFCub.ar(XLine.kr(100, 15000 ,6), 0, 0.1) }.scope(1, zoom: 4); // 通过XLine函数,使得频率在6秒内从100Hz线性变化到1500Hz
  • LFTri 是生成三角形信号的UGen:
{ LFTri.ar(800, 0, 0.1) }.scope(1, zoom: 4);
{ LFTri.ar(XLine.kr(100, 15000, 6), 0, 0.1) }.scope(1, zoom: 4);
  • LFSaw 生成的是锯齿(Sawtooth)波:
{ LFSaw.ar(100, 0, 0.1) }.scope(1, zoom: 4);
{ LFSaw.ar(XLine.kr(100, 15000, 6), 0, 0.1) }.scope(1, zoom: 4);
  • Impulse 生成的是单次采样的刺激(impulse)信号:
{ Impulse.ar(100, 0, 0.1)}.scope(1, zoom: 4);
{ Impulse.ar(XLine.kr(100, 15000, 6), 0, 0.1)}.scope(1, zoom: 4);

下面两个函数有相同的参数:frequency(频率)、phase(相位)、width(宽度,0到1的数,每一次脉冲的宽度)、mul(振幅的乘数,介于0到1的数,输出是原值与它相乘)和add(上下位移):

  • LFPulse 生成的是脉冲(Pulse)信号:
{ LFPulse.ar(XLine.kr(100, 15000, 6), 0, 0.5, 0.1)}.scope(1, zoom: 4); // 宽度为0.5
{ LFPulse.ar(100, 0, MouseY.kr(0, 1), 0.1)}.scope(1, zoom: 4); // 使用了MouseY函数,可以通过上下移动鼠标指针来改变宽度
  • VarSaw 生成的是工作周期可变的锯齿波(Sawtooth)信号:
{ VarSaw.ar(XLine.kr(100, 15000, 6), 0, 0.2, 0.1)}.scope(1, zoom: 4); // 宽度设置为0.2,在这个函数中的意义是占空比(duty cycle,周期内工作时间与总时间的比值)
{ VarSaw.ar(100, 0, MouseY.kr(0, 1), 0.1)}.scope(1, zoom: 4); // 上下移动鼠标指针来改变占空比
  • SyncSaw 用于实现锯齿波信号硬同步,它的参数有四个:syncFreq(同步频率,基础信号的频率)、sawFreq(锯齿频率,从属的同步锯齿信号波的频率,始终比第一个参数大)、mul、add。它的效果同移动共振峰或脉冲信号宽度调制相似。
{ SyncSaw.ar(100, MouseX.kr(100, 1000), 0.1)}.scope(1, zoom: 4);
{ SyncSaw.ar(100, Line.kr(100, 800, 12), 0.1)}.scope(1, zoom: 4);

频带限制振荡器(Band Limited Oscillators)

这类振荡器主要有SinOsc, FSinOsc, Blip, Saw和Pulse这五个,由于它们是有频带限制的,所以不会出现混叠现象:

SinOsc 和 FSinOsc 有相同的参数: frequency, phase, mul, add

  • SinOsc 十分常用,用于产生正弦波:
{ SinOsc.ar(SinOsc.kr(0.2, 0, 400, 800), 0, 0.1) }.scope(1); // 频率为用SinOsc的control rate产生的一个变化值
{ SinOsc.ar(800, 0, 0.1) }.scope(1); // 频率为800,相位是0,振幅变为十分之一
  • FSinOsc 用于产生十分快速的正弦波(每个输出采样2个PowerPC指令),它产生的正弦波比 SinOsc 更纯正,更快速,然而频率的改变会影响振幅(频率升高增大振幅,频率减小降低振幅):
{ FSinOsc.ar(800, 0, 0.1)}.scope(1, zoom: 4);
{ FSinOsc.ar(FSinOsc.kr(FSinOsc.kr(0.2, 0.8, 10), 0, 400, 800), 0, 0.1)}.scope(1, zoom: 4); // 多个FSinOsc在频率叠加,最终会失控
  • Blip 用于产生频带限制的刺激(Band Limited ImPulse generator),在MUSIC-N语言里同“buzz”相同,其参数列表为 frequency, numHarmonics(一个周期内的谐波数), mul, add:
{ Blip.ar(XLine.kr(20000, 200, 6), 100, 0.2)}.scope(1, zoom: 4); // 可以看出产生的信号在开始阶段有很严重的混叠现象
{ Blip.ar(200, Line.kr(1, 100, 20), 0.2) }.scope(1); // 改变谐波数,从1到100来进行过渡
  • Saw 用于产生频带限制的锯齿波信号,参数为frequency, mul, add:
{ Saw.ar(XLine.kr(20000, 200, 6), 0.2)}.scope(1, zoom: 4);
{ Saw.ar(XLine.kr(100, 15000, 6), 0.2)}.scope(1, zoom: 4);
  • Pulse 用于产生频带限制的脉冲信号,参数为frequency, width, mul, add
{ Pulse.ar(XLine.kr(40, 4000, 6), 0.1, 0.2)}.scope(1, zoom: 4); // 频率从40线性变换到4000,width设置为0.1
{ Pulse.ar(200, SinOsc.kr(0.2).range(0.01, 0.99), 0.2)}.scope(1, zoom: 4); // 将频率固定为200,宽度以正弦波形在0.01到0.99之间波动
{ Pulse.ar(200, Line.kr(0.01, 0.99, 8), 0.2) }.scope(1, zoom: 4); // 宽度从0.01到0.99线性变换
  • Klang 用于产生一个由固定频率的正弦信号组合而成的信号,与一个个振荡器地写再组合起来相比,Klang提供了更多的便利,其参数格式为 specificationsArrayRef(由三个数组(frequencies、amplitudes、phases)组合而成的一个数组,这三个数组分别是组合的正弦信号的频率、振幅和相位),freqscale(用于与所有的正弦波的频率相乘的比例因子),freqoffset(加到所有频率的一个因子)
{ Klang.ar(`[[800, 1000, 1200], [0.3, 0.3, 0.3], [pi, pi, pi]], 1, 0) * 0.4}.scope(1);
{ Klang.ar(`[[800, 1000, 1200], nil, nil], 1, 0) * 0.25 }.scope(1);
{ Klang.ar(`[ Array.rand(12, 600.0, 1000.0), nil, nil ], 1, 0) * 0.05 }.scope(1); // 以12个随机生成的介于600和1000之间的随机数为频率组合
{ Klang.ar(`[ {exprand(400, 2000)}.dup(16), nil, nil], 1, 0) * 0.04}.scope(1); // 以16个介于400到2000的指数分布的随机数作为频率组合

波表振荡器(Table Oscillators)

波表振荡器是使用由服务器(server)分配的一个缓存(buffer)来产生声音的一系列振荡器,主要有Osc, COsc, VOsc, VOsc3 :

  • Osc 从线性插值的波表(Wavetable)中相关数据,这个波表一般存储在一个缓存(buffer)中,参数为buffer number(buffer的编号,在申请时会明确), frequency, phase, mul, add
(
b = Buffer.alloc(s, 2048, 1, bufnum: 80); // 申请一个编号为80的buffer,s即代表服务器
b.sine1(1.0/(1..6), true, true, true); // 初始化buffer,sine1的参数为amps, normalize, asWavetable, clearFirst:
)
{ Osc.ar(80, 100, 0, 0.1) }.scope(1, zoom:4); // 读取b来输出信号

// 可以通过以下语句来改变b的值,产生的信号随之改变了
b.sine1(1.0/(1..12));
b.sine1(1.0/(1..24));
b.sine1(1.0/(1..32));
b.sine1([1.0/(1,3..12), 0].flop.flat.postln);
b.sine1([1.0/(1,3..32).squared, 0].flop.flat.postln);
b.sine1((1.dup(4) ++ 0.dup(8)).scramble.postln);
b.sine1((1.dup(4) ++ 0.dup(8)).scramble.postln);
b.sine1((1.dup(4) ++ 0.dup(8)).scramble.postln);
b.sine1((1.dup(4) ++ 0.dup(8)).scramble.postln);
b.sine1({1.0.rand2.cubed}.dup(8).round(1e-3).postln);
b.sine1({1.0.rand2.cubed}.dup(12).round(1e-3).postln);
b.sine1({1.0.rand2.cubed}.dup(16).round(1e-3).postln);
b.sine1({1.0.rand2.cubed}.dup(24).round(1e-3).postln);
  • COsc 可以用于合并两个信号,输出的信号是 (freq ± (beats / 2)),参数为 buffer number, frequency, beat frequency, mul, add
{ COsc.ar(80, 100, 1, 0.1) }.scope(1, zoom:4); // beat frequency设置为1
  • VOsc 用于使用波表产生交叉衰落(crossfade)的振荡器
  • VOsc3 实现三个 VOsc 的合成

总结

各种振荡器类的官方文档已经以超链接的形式在文章中给出了,再次声明本文是参考官网的教程 Tour of UGens 写成,并根据个人需要进行了部分删减和着重处理,希望对大家有所帮助

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值