Skip to content

Instantly share code, notes, and snippets.

@Sciss
Last active November 18, 2015 16:48
Show Gist options
  • Select an option

  • Save Sciss/b67db2085d40cd05c08c to your computer and use it in GitHub Desktop.

Select an option

Save Sciss/b67db2085d40cd05c08c to your computer and use it in GitHub Desktop.
/*---
Adapted from: Designing Sound in SuperCollider
Source: https://en.wikibooks.org/wiki/Designing_Sound_in_SuperCollider
*/
/*---
24. Pedestrians
*/
play {
SinOsc.ar(2500) * 0.2 * LFPulse.ar(5)
}
/*---
25. Phone Tones
*/
// 25.2 CCITT dialing tone
play {
Pan2.ar(Mix(SinOsc.ar(Seq(350, 440)))) * 0.2
}
// 25.3: Filter to approximate the transmission medium
val bus = Bus.audio(s)
val filter = play {
val in = In.ar("in".kr(bus.index)).clip2(0.9)
val f1 = BPF.ar(in, 2000, 1.0/12)
val f2 = BPF.ar(f1 * 0.5, 400, 1.0/3) + (f1.clip2(0.4) * 0.15)
HPF.ar(HPF.ar(f2, 90), 90) * 100
}
// 25.4: The filter applied to the dialing tone
val source = play(target = filter, addAction = addBefore) {
val onoff = MouseX.kr > 0.2
val sig = Mix(SinOsc.ar(Seq(350, 440))) * onoff * 0.2
Out.ar("out".kr(bus.index), sig)
}
source.free()
// 25.5a: Ringing tone
val source = play(target = filter, addAction = addBefore) {
val onoff = LFPulse.ar(1.0/6, width = 1.0/3)
val sig = Mix(SinOsc.ar(Seq(480, 440))) * onoff * 0.2
Out.ar("out".kr(bus.index), sig)
}
source.free()
// 25.5b: Busy tone
val source = play(target = filter, addAction = addBefore) {
val onoff = LPF.ar(LFPulse.ar(2), 100)
val sig = Mix(SinOsc.ar(Seq(480, 620))) * onoff * 0.2
Out.ar("out".kr(bus.index), sig)
}
source.free()
// 25.6: Pulse dialing, before DTMF
val source = play(target = filter, addAction = addBefore) {
val n = "number".kr
val number = Select.kr(n < 0.5, Seq[GE](n, 10)) // zero is represented by 10 clicks!
val t_trig = "t_trig".tr
number.poll(t_trig)
val onoff = Trig1.ar(t_trig, number * 0.1)
val trigs = Impulse.ar(10) * onoff
val son = Trig1.ar(trigs, 0.04)
son
}
source.set("t_trig" -> 1, "number" -> util.Random.nextInt(10))
source.free(); filter.free(); bus.free()
/*---
Practicals: Nature
34. Fire
*/
// 34.3: simplest random hissing sound
play {
WhiteNoise.ar(LFNoise2.kr(1))
}
// 34.4: square it
play {
WhiteNoise.ar(LFNoise2.kr(1).squared)
}
// 34.5: more
play {
HPF.ar(WhiteNoise.ar, 1000) * LFNoise2.kr(1).squared.squared
}
// 34.6: a simple single crackle
play {
WhiteNoise.ar * Line.ar(1, 0, 0.02, doneAction = freeSelf)
}
// 34.7: many crackles
play {
WhiteNoise.ar * EnvGen.ar(Env.perc(0, 0.02, curve = Curve.parametric(0)), Dust.kr(1))
}
// 34.8: more variation
play {
val trigs = Dust.kr(1)
val durScale = TRand.kr(1, 1.5, trigs) // vary duration between default 20ms and 30ms
val resFreq = TExpRand.kr(100, 1000, trigs) // different resonant frequency for each one
val son = WhiteNoise.ar * EnvGen.ar(Env.perc(0, 0.02, curve = Curve.parametric(0)),
gate = trigs, timeScale = durScale)
son + BPF.ar(son, resFreq, 20)
}
// 34.9: woof
play {
LPF.ar(WhiteNoise.ar, 30) * 100
}
// 34.10: woosh
play {
BPF.ar(WhiteNoise.ar, 30, 0.2) * 20
}
// 34.11: shape
play {
LeakDC.ar(LeakDC.ar(BPF.ar(WhiteNoise.ar, 30, 0.2) * 50).clip2(0.9)) * 0.5
}
// 34.12: putting it all together
def fireGen = {
// A common noise source
val noise = WhiteNoise.ar
// Hissing
val hissing = HPF.ar(noise, 1000) * LFNoise2.kr(1).squared.squared
// Crackle
val trigs = Dust.kr(1)
val durScale = TRand.kr(1, 1.5, trigs) // vary duration between default 20ms and 30ms
val resFreq = TExpRand.kr(100, 1000, trigs) // different resonant frequency for each one
val crack1 = noise * EnvGen.ar(Env.perc(0, 0.02, curve = Curve.lin), trigs, timeScale = durScale)
val crackles = crack1 + BPF.ar(crack1, resFreq, 20)
// Flame
val lapping = LeakDC.ar(LeakDC.ar(BPF.ar(noise, 30, 0.2) * 50).clip2(0.9)) * 0.5
// Combine them:
Mix(Seq(crackles * 0.1, hissing * 0.3, lapping * 0.6)) * 3
}
play { fireGen }
// 34.13: poly
play {
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)
}
/*---
35. Bubbles
*/
// 35.5: producing a repeating but random-seeming pattern of triggers
val sdBubbleTrigs = SynthDef("bubbletrigs") {
val out = "out".kr
val probability = "probability".kr(0.5)
// These two lines create a loop of zeroes
// with some ones (i.e. triggers) placed at prime-number locations
val sz = 200
val buf = LocalBuf(sz)
val a = Seq.tabulate(sz)(i =>
if (Set(29, 37, 47, 67, 89, 113, 157, 197).contains(i)) 1 else 0
)
SetBuf(buf, a)
// playbuf by default will use the server's rate, but we want one item every 15ms
val pb = PlayBuf.kr(1, buf, 0.015.reciprocal / ControlRate.ir, loop = 1)
// Randomly discard half of them, to remove too much obvious looping
val trigs = CoinGate.kr(probability, pb)
// Let's poll to watch the events appearing
trigs.poll(trigs) // XXX TODO -- no triggers?
Out.kr(out, trigs)
}
val x = sdBubbleTrigs.play()
x.free()
// 35.8: sound of a bubble
val sdBubbleBub = SynthDef("bubblebub") {
val out = "out".kr
val t_trig = "t_trig".tr
val attack = "attack".kr(0.01)
val decay = "decay".kr(0.08)
val pitchCurveLen = "pitchCurveLen".kr(0.1)
val freq = "freq".kr(1000)
val doneAction = "doneAction".kr(0)
val amp0 = "amp".kr(0.1)
val amp = amp0 * EnvGen.ar(Env.perc(attack, decay), t_trig, doneAction = doneAction)
import Env.{Segment => Seg}
val pchEnv = Env(1, List(Seg(0.003, 1), Seg(1, 2.718, Curve.exp)))
val pitch = freq * EnvGen.ar(pchEnv, t_trig, timeScale = pitchCurveLen)
val son = SinOsc.ar(pitch)
// high-pass to remove any lowpitched artifacts, scale amplitude
val sig = HPF.ar(son, 500) * amp * 10
Out.ar(out, sig)
}
val x = sdBubbleBub.play()
x.set("t_trig" -> 1)
/*---
36. Running water
*/
// 36.3: random-frequency sines
play {
SinOsc.ar(LFNoise0.kr(170).linlin(-1, 1, 800, 2400)) * 0.3
}
// 36.4: rising pitches
def rising() = {
val trigs = Dust.kr(170)
val freq =
// Generally choose from a varied base freq
TExpRand.kr(800, 2000, trigs) +
// Wobbly variation
LFNoise2.kr(20) * 300 +
// General tendency for upward rise
EnvGen.kr(Env.perc(level = 17), trigs)
SinOsc.ar(freq) * 0.3
}
play(rising())
// hmmm, let's try combining a few of these in parallel.
// do we sound like a river yet?
play {
Mix.fill(6)(rising()) / 6
}
/*---
38. Rain
*/
// 38.1: Fluid sphere impact
def dropletOnHard = {
val dur = "dur".kr(0.0005)
import Env.{Segment => S}
import Curve.{parametric => par}
Env(0, List((1, dur/2, par(-4)), (0, dur/2, par(+4))))
}
// 38.3: obtaining a Gaussian noise distribution
play {
val sig: GE = Seq.fill(2)(Mix.fill(12)(WhiteNoise.ar))
sig / 24
}
play {
val amount = MouseX.kr(0,1) // move mouse left/right to change amount
val n1 = WhiteNoise.ar.abs * amount + (1-amount)
val n2 = WhiteNoise.ar(2 * math.Pi)
val gaussian = (n1.log * -2).sqrt * n2.cos
(Seq(gaussian, gaussian): GE) * 0.5
}
// 38.4: raindrop pressure on solid ground
play {
val noise = Mix.fill(12)(WhiteNoise.ar)
val gaus = LPF.ar(BPF.ar(noise, 50, 1/0.4), 500)
//
val sin = SinOsc.ar(gaus.linlin(-1, 1, 40, 80)) * gaus.squared * 10
val clip = (sin - 0.35).max(0)
val osc = Mix.fold(clip, 2)(HPF.ar(_, 500))
Seq(osc, osc)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment