跳转到内容

SuperCollider 中的声音设计/吱呀作响的门

来自维基教科书,开放的书籍,开放的世界

图 32.3:木门的共振峰

[编辑 | 编辑源代码]
(
~woodfilter = { |input|
	var freqs, rqs, output;
	// Note: these freqs are as given in the diagram:
	freqs = [62.5, 125, 250, 395, 560, 790];
	// The Q values given in the diagram (we take reciprocal, since that's what BPF unit wants)
	rqs   = 1 / [1, 1, 2, 2, 3, 3];
	// in the text, andrew says that the freqs follow these ratios, 
	// which give a very different set of freqs...:
	// freqs = 125 * [0.5, 1, 1.58, 2.24, 2.92, 2, 2.55, 3.16];
	
	//Now let's apply the parallel bandpass filters, plus mix in a bit of the original:
	output = BPF.ar(input, freqs, rqs).sum + (input*0.2);

};

// Now let's use this function in something - some dust impulses tap-tap-tapping on the door:
x = {
	Pan2.ar(~woodfilter.value(  LPF.ar(Dust.ar(10), 10000)  ))
}.play;
// Doesn't sound much like a door? Compare it to the raw tapping sound (edit the above).
)


图 32.4:响应施加力的粘滑运动

[编辑 | 编辑源代码]
(
~stickslip = { |force|
	var inMotion, slipEvents, forceBuildup, evtAmp, evtDecayTime, evts;
	force = force.lag(0.1); // smoothing to get rid of volatile control changes
	
	inMotion = force > 0.1; // static friction: nothing at all below a certain force
	
	// slip events are generated at random with freqency proportional to force.
	// I originally used Dust to generate random events at a defined frequency, but
	// that lacks the slight "pitched" sound of the creaky door. Here we use Impulse
	// to generate a frequency, but we add some noise to its frequency to try and 
	// avoid it getting too perfectly regular.
	slipEvents = inMotion * Impulse.ar(force.linlin(0.1, 1, 1, 1/0.003) * LFDNoise1.ar(50).squared.linexp(-1,1, 0.5, 2).poll);
	
	forceBuildup = Phasor.ar(slipEvents, 10 * SampleDur.ir, 0, inf).min(1);
	
	// Whenever a slip event happens we use Latch to capture the amount of
	// force that had built up.
	evtAmp = Latch.ar(Delay1.ar(forceBuildup.sqrt), slipEvents);
	evtDecayTime = evtAmp.sqrt;
	// The book applies square-root functions to shape the dynamic range of the events.
	// Remember that square-root is computationally intensive, so for efficient 
	// generation we might want to change it to (e.g.) a pre-calculated envelope.
	
	// Now we generate the events
	evts = EnvGen.ar(Env.perc(0.001, 1), slipEvents, evtAmp, 0, evtDecayTime * 0.01);
};
// Let's plot 4 seconds worth, with steadily increasing force.
// Events should appear more frequent but less violent as the plot progresses.
{~stickslip.value(Line.kr(0,1,4))}.plot(4);
)

图 32.5:模拟矩形门框的平行延迟

[编辑 | 编辑源代码]
(
~squarepanel = { |input|
	var times, filt;
	// times in milliseconds, converted to seconds:
	times = [4.52, 5.06, 6.27, 8, 5.48, 7.14, 10.12, 16] * 0.001;
	filt = DelayC.ar(input, times, times).mean;
	filt = HPF.ar(filt, 125);
	filt * 4
};
)

图 32.6:将所有内容整合在一起

[编辑 | 编辑源代码]

以下内容结合了本页之前定义的函数,以创建一个 你可以自己推动的门!

在运行此代码之前,将鼠标移到屏幕左侧。然后将鼠标移动到右侧和左侧,以控制门上的力。

x = {~squarepanel.value(~woodfilter.value(~stickslip.value(MouseX.kr(0,1))))}.play
华夏公益教科书