Designing Sound in SuperCollider/Fire

Fig 34.3: simplest random hissing sound edit

{WhiteNoise.ar(LFNoise2.kr(1))}.play

Fig 34.4: square it edit

Squaring the noise gives it a more useful dynamic range, with rare loud bursts

{WhiteNoise.ar(LFNoise2.kr(1).squared)}.play

Fig 34.5: more edit

Add another .squared for even stronger effect on the dynamics, and use a high-pass filter to make the hiss more hissy

{HPF.ar(WhiteNoise.ar, 1000) * LFNoise2.kr(1).squared.squared}.play

Fig 34.6: a simple single crackle edit

{WhiteNoise.ar * Line.ar(1, 0, 0.02, doneAction: 2)}.play

Fig 34.7: many crackles edit

If we use a proper envelope generator instead of a simple line, we can retrigger it randomly with Dust to give random crackles of a controllable density

{WhiteNoise.ar * EnvGen.ar(Env.perc(0, 0.02, curve: 0), Dust.kr(1))}.play

Fig 34.8: more variation edit

Add more variation by modulating the duration and the filter frequency for each event

(
{
	var trigs, durscale, son, resfreq;
	trigs = Dust.kr(1);
	durscale = TRand.kr(1, 1.5, trigs); // vary duration between default 20ms and 30ms
	resfreq = TExpRand.kr(100, 1000, trigs); // different resonant frequency for each one
	son = WhiteNoise.ar * EnvGen.ar(Env.perc(0, 0.02, curve: 0), trigs, timeScale: durscale);
	son = son + BPF.ar(son, resfreq, 20);
}.play
)

Fig 34.9: woof edit

Simple attempt at the low "woofing" noise made by the flames themselves

{LPF.ar(WhiteNoise.ar, 30) * 100}.play

Fig 34.10: woosh edit

// another component we could use to build up a flamey sound

{BPF.ar(WhiteNoise.ar, 30, 0.2) * 20}.play

Fig 34.11: shape edit

Shaping the dynamic range and discarding some of the lower frequencies, allowing a little clipping to give a less static sound.

{LeakDC.ar(LeakDC.ar(BPF.ar(WhiteNoise.ar, 30, 0.2) * 50).clip2(0.9)) * 0.5}.play

Fig 34.12: putting it all together edit

(
~firegen = {
	var trigs, durscale, resfreq;
	var noise, hissing, crackles, lapping;
	// A common noise source
	noise = WhiteNoise.ar;
	// Hissing
	hissing = HPF.ar(noise, 1000) * LFNoise2.kr(1).squared.squared;
	// Crackle
	trigs = Dust.kr(1);
	durscale = TRand.kr(1, 1.5, trigs); // vary duration between default 20ms and 30ms
	resfreq = TExpRand.kr(100, 1000, trigs); // different resonant frequency for each one
	crackles = noise * EnvGen.ar(Env.perc(0, 0.02, curve: 0), trigs, timeScale: durscale);
	crackles = crackles + BPF.ar(crackles, resfreq, 20);
	// Flame
	lapping = LeakDC.ar(LeakDC.ar(BPF.ar(noise, 30, 0.2) * 50).clip2(0.9)) * 0.5;
	// Combine them:
	([crackles, hissing, lapping] * [0.1, 0.3, 0.6]).sum * 3
};
~firegen.play
)

Fig 34.13: poly edit

Let's have four of the above, each filtered differently, for a composite effect

(
{
	BPF.ar(~firegen,  600, 1/0.2) +
	BPF.ar(~firegen, 1200, 1/0.6) +
	BPF.ar(~firegen, 2600, 1/0.4) +
	HPF.ar(~firegen, 1000)
}.play
)