在 SuperCollider 中设计声音 / 昆虫
外观
(
a = {
var modulator, mod1, mod2, mod3;
// repeat time is 0.7s: equates to 1.43 Hz.
modulator = LFSaw.ar(1.43, 1, 0.5, 0.5);
mod2 = (modulator * 40.6 * 2pi).cos.squared;
mod3 = modulator * 3147;
mod3 = (mod3 * 2pi).cos + ((mod3 * 2 * 2pi).cos * 0.3);
mod1 = ((Wrap.ar(modulator.min(0.1714) * 5.84) - 0.5).squared * (-4) + 1) * (mod2 * mod3);
mod1 = (mod1 * 0.1)!2;
}.play;
)
// To stop:
a.free;
(
b = {
var trig, seq, demand, cricket;
// instead of [metro], Impulse.kr is used here. Delta t = 17 ms equates to 58.82 Hz.
trig = Impulse.kr(58.82);
// the main idea of the following line was to use an approach
// that uses the same coefficients as described in the pd patch
seq = Dseq(Array.fill(41, {|i| if(i<7, {(i+2)/9},{0}) }),inf);
demand = Demand.kr(trig,0,seq);
// Implementation of the pd code for pulses including amplitude grow:
// cricket = EnvGen.ar(Env.new([0, 1, 1, 0], [0.0001, 0.0001, 0]), trig) * demand;
// 2nd implementation: pure data seemed to slightly disobey its own specifications,
// so I analysed the waveform and came up with this:
cricket = EnvGen.ar(Env.new([0, 1, 0], [4/44100, 0]), trig) * demand;
cricket = OnePole.ar(cricket, exp(-2pi * (1000 * SampleDur.ir)));
cricket = (
// changed the Q factor of the first 3 BPFs to approximate farnells sound
BPF.ar(cricket, 4500 + ((0..2)*50), 300.reciprocal, 100)).sum
+ BPF.ar(cricket, 9000, 500.reciprocal, 42
);
cricket = ((cricket - OnePole.ar(cricket, exp(-2pi * (4000 * SampleDur.ir)))) * 0.5)!2;
}.play;
)
// To stop:
b.free;
(
c = {
var sig, trig, seq, freq, mul, vals;
trig = Impulse.kr(0.2);
vals = [
[0.5, 128],
[8,6],
[30,3]
];
freq = TChoose.kr(trig, vals);
sig = WhiteNoise.ar;
// The one pole filters in pure data and SC differ, so I changed the coefficents
// a little. Also the multiplication by 5 is not in the book, but helps to
// approach the audible result of Farnells patch.
sig = (sig - OnePole.ar(sig, exp(-2pi * (8000 * SampleDur.ir))));
sig = (sig - OnePole.ar(sig, exp(-2pi * (8000 * SampleDur.ir))));
sig = OnePole.ar(sig, exp(-2pi * (10000 * SampleDur.ir)));
sig = OnePole.ar(sig, exp(-2pi * (10000 * SampleDur.ir)));
sig = sig * 5;
sig = BPF.ar(sig, [7500, 5500], 40.reciprocal).sum * SinOsc.ar(500);
sig = sig * (1 / (SinOsc.ar( freq[0], 0, freq[1] ).squared + 1));
sig = (sig - OnePole.ar(sig, exp(-2pi * (4000 * SampleDur.ir)))) * 4.dup;
}.play;
)
// To stop:
c.free;
pd 贴片中的可调整参数可以通过鼠标移动来控制:MouseX 控制翅膀频率,MouseY 控制翅膀共振。
(
SynthDef(\houseflyWing, { |out=0|
var sig, downstroke, upstroke, wingFreq, wingRes;
// this is already a preparation for fig 50.14 and is not described
// in the pure data patch on fig 50.13
wingFreq = In.ar(10,2);
wingRes = In.ar(20,2);
// Also, it is prepared for some other input from a different source,
// to not only control the patch with the mouse movement.
// See also the following URL for more information about the next lines:
// http://supercollider.sourceforge.net/wiki/index.php/Boolean_logic_in_the_server
wingFreq = Select.ar(wingFreq > 0, [K2A.ar(MouseX.kr(0, 300)), wingFreq]);
wingRes = Select.ar(wingRes > 0, [K2A.ar(MouseY.kr(3,5)), wingRes]);
sig = LFSaw.ar(wingFreq, 1, 0.5, 0.5);
sig = ((sig * 0.2).min(sig * (-1) + 1)).min(sig.min(sig * (-1) + 1));
sig = (sig * 6 - 0.5) * 2;
downstroke = (wingRes) * sig.min(0);
downstroke = (Wrap.ar(downstroke) * 2pi).cos * sig.min(0) * 0.5 + sig.min(0);
upstroke = sig.max(0).cubed * 2;
sig = downstroke + upstroke;
sig = (sig - OnePole.ar(sig, exp(-2pi * (700 * SampleDur.ir)))).dup * 0.05;
Out.ar(out, sig);
}).add;
x = Synth(\houseflyWing);
)
在运行下面的其他代码块时保持运行...
(
SynthDef(\buzzingHousefly, {
var beatingFreq, resonanceMod;
beatingFreq = OnePole.ar(WhiteNoise.ar, exp(-2pi * (4 * SampleDur.ir)));
beatingFreq = OnePole.ar(beatingFreq, exp(-2pi * (4 * SampleDur.ir)));
beatingFreq = beatingFreq * 700 + 220;
resonanceMod = OnePole.ar(WhiteNoise.ar, exp(-2pi * (5 * SampleDur.ir)));
resonanceMod = OnePole.ar(resonanceMod, exp(-2pi * (5 * SampleDur.ir)));
Out.ar(10, [beatingFreq, (resonanceMod * 3) + beatingFreq]);
Out.ar(20, (resonanceMod * 40 + 5)!2 );
}).add;
y = Synth(\buzzingHousefly);
)
// now again the housefly wings are controlled by the mouse movement.
y.free;
// To stop:
x.free;
如果在 Synth(\houseflyWing) 之前执行了 Synth(\buzzingHousefly),则需要执行以下行才能听到 Synth(\buzzingHousefly) 的效果。这是因为本例中使用了 In.ar 和 Out.ar 来在两个贴片之间进行通信,并且在使用 In.ar 时,始终需要牢记服务器上合成器的执行顺序。(另请参阅帮助文件:执行顺序)。
Synth(\buzzingHousefly, addAction: \addToHead);