跳轉到內容

SuperCollider/Bubbles 中的聲音設計

來自華夏公益教科書,開放的書籍,為開放的世界

圖 35.5:產生一個重複但看起來隨機的觸發器模式

[編輯 | 編輯原始碼]

首先,我們將建立一個可重複使用的 synthdef,它輸出觸發器(但不輸出聲音)

(
SynthDef(\bubbletrigs, {|out=0, probability=0.5|
	var trigs, buf, a;
	// These two lines create a loop of zeroes 
	// with some ones (i.e. triggers) placed at prime-number locations
	a = {0}.dup(200);
	[29, 37, 47, 67, 89, 113, 157, 197].do{|val| a[val] = 1};
	buf = a.as(LocalBuf);
	// playbuf by default will use the server's rate, but we want one item every 15ms
	trigs = PlayBuf.kr(1, buf, 0.015.reciprocal / (s.sampleRate / s.options.blockSize), loop: 1);
	// Randomly discard half of them, to remove too much obvious looping
	trigs = CoinGate.kr(probability, trigs);
	// Let's poll to watch the events appearing
	trigs.poll(trigs);
	Out.kr(out, trigs);
}).add
)

// Then we'll play it:
x = Synth(\bubbletrigs); // watch the post window to see the bubble events happening (no sound yet!)
x.free;

圖 35.8:氣泡的聲音

[編輯 | 編輯原始碼]
(
SynthDef(\bubblebub, {	|out=0, t_trig=0, attack=0.01, decay=0.08, pitchcurvelen=0.1, freq=1000, doneAction=0, amp=0.1|
	var pitch, son;
	amp   = amp * EnvGen.ar(Env.perc(attack, decay).delay(0.003), t_trig, doneAction: doneAction);
	pitch = freq * EnvGen.ar(Env.new([0,0,1],[0,1]).exprange(1, 2.718), t_trig, timeScale: pitchcurvelen);
	son = SinOsc.ar(pitch);
	// high-pass to remove any lowpitched artifacts, scale amplitude
	son = HPF.ar(son, 500) * amp * 10;
	Out.ar(out, son);
}).store
)

x = Synth(\bubblebub);
x.set(\t_trig, 1); // run this line multiple times, to get multiple (very similar) bubbles!
x.free;


圖 35.9:四個氣泡系統,以隨機方式簡單觸發。

[編輯 | 編輯原始碼]
(
s.bind{	
	// Here we'll create busses to hold the triggers, passing them from synth to synth
	~maintrigbus = Bus.control(s, 1);
	~bubtrigbus = Bus.control(s, 4);
	// Note how we make sure things are running in the desired order, using \addAfter
	~trigs = Synth(\bubbletrigs, [\out: ~maintrigbus]);
	// This reads the main trig and puts each trig on a randomly-chosen bus
	~randomdistrib = {
		var trig, which;
		trig = In.kr(~maintrigbus);
		which = TIRand.kr(0,3, trig);
		// or try the Stepper instead of TIRand for "round-robin" selection:
		// which = Stepper.kr(trig, 0, 0, 3);
		which = which.poll(trig);
		Out.kr(~bubtrigbus.index + which, trig);
	}.play(target: ~trigs, addAction: \addAfter);
	
	s.sync;
	
	~bubs = [2400, 2600, 2500, 2700].collect{|afreq|
		Synth(\bubblebub, [\freq, afreq], target: ~randomdistrib, addAction: \addAfter);
	};
	
	s.sync;
	
	// "map" allows us to push the triggers from the control bus to the "t_trig" inputs:
	~bubs.do{|bub, bubindex| bub.map(\t_trig, ~bubtrigbus.index + bubindex) };
};
)

注意,我們不需要使用 "bubbletrigs" 合成器(它是 pd 示例的直接移植),我們可以使用 Patterns 來觸發氣泡合成器。這是一種不同的資源管理模型:我們不是擁有四個始終執行的合成器,它們重新觸發以建立新的氣泡,而是根據需要建立合成器,並在完成後釋放。

(
p = Pbind(
	\instrument, \bubblebub,
	// The commented version is a bit like the above timings...
	// \dur, Pseq([29, 37, 47, 67, 89, 113, 157, 197, 200].differentiate * 0.015, inf),
	// ...but happily we have useful random-distrib generators. Ppoisson would be ideal but is misbehaving for me!
	\dur, Pgauss(0.3, 0.2),
	\freq, Pwhite(0.0,1,inf).linexp(0,1, 1000, 3000),
	// doneAction of two allows the synths to free themselves. See  "UGen-doneActions".openHelpFile
	\doneAction, 2
).play
)
p.stop

下一個稍微複雜一些 - 我們按照書中的做法,使較小的氣泡具有(a)更高的音調(b)更低的音量(c)更短的持續時間。為了將這些值連線在一起,我們定義了一個 "sizefactor",並在每個引數中使用 Pkey 重用它。

(
p = Pbind(
	\instrument, \bubblebub,
	\sizefactor, Pwhite(0.0,1,inf),
	\dur, Pgauss(0.3, 0.2),
	\freq,  Pkey(\sizefactor).linexp(0, 1, 1000, 3000),
	\amp ,  Pkey(\sizefactor).linlin(0, 1, 0.15, 0.04), 
	\decay, Pkey(\sizefactor).linlin(0, 1, 0.05, 0.08), 
	\doneAction, 2
).play
)
p.stop
華夏公益教科書