pulusound

<<< back to home page

supercaw

posted 2026-07-19

recently, sqx made caw (source), a lovely crow synth that works in the browser. i wanted to port it to SuperCollider, so here is an attempt:

(
SynthDef(\caw, { |out=0, freq=50, freq1=600, duration=0.5, modfreq=63, envpeak=0.25, envshape=0.3, modgain0=325, modgain1=75, modshape=0.5, bpfreq=1150, bprq=0.1, hpfreq=1100, hprq=0.6, formfreq=1600, formrq=0.5, formgain=0.8, dist=0.4, pan=0, amp=0.5|
    var env, mf, sig;
    env = EnvGen.ar(Env.perc(envpeak*duration, 1.0-envpeak*duration, curve: \linear), doneAction: Done.freeSelf) ** envshape;
    mf = SinOsc.ar(modfreq).max(0) ** modshape;
    sig = Saw.ar(env.linlin(0, 1, freq, freq1) + (mf * env.linlin(0, 1, modgain0, modgain1)));
    sig = BPF.ar(sig, bpfreq, bprq, bprq.sqrt.reciprocal);
    sig = HPF.ar(sig, hpfreq, hprq, hprq.sqrt.reciprocal);
    sig = sig + (formgain * BPF.ar(sig, formfreq, formrq, formrq.sqrt.reciprocal));
    sig = LeakDC.ar(sig);
    sig = (sig * env * dist).tanh * 3 * amp;
    sig = Pan2.ar(sig, pan);
    Out.ar(out, sig);
}).add;
)

plus a pattern that plays randomized caws:

(
Pdef(\caw, Pbind(
    \instrument, \caw,
    \duration, Pwhite(0.2, 0.35),
    \envpeak, Pwhite(0.3, 0.3),
    \envshape, Pwhite(0.2, 0.4),
    \freq, Pwhite(0, 100),
    \freq1, Pwhite(550, 720),
    \modfreq, Pwhite(60, 65),
    \modgain0, Pwhite(300, 350),
    \modgain1, Pwhite(50, 100),
    \modshape, Pwhite(0.4, 0.6),
    \dist, Pwhite(0.3, 0.5),
    \formfreq, Pwhite(1500, 1700),
    \formgain, Pwhite(0.5, 1.1),
    \formrq, Pwhite(0.8, 0.9),
    \bpfreq, Pwhite(1000, 1300),
    \bprq, Pwhite(0.2, 0.3),
    \hpfreq, Pwhite(1000, 1200),
    \hprq, Pwhite(0.7, 0.8),
    \dur, 0.5,
    \amp, 0.6
)).play
)

it does not sound quite as good as the original, but it's a start. still need to look deeper into the differences.

also, a SuperDirt version:

SynthDef(\supercaw, { |out=0, freq, voice=0.5, sustain=1, rate=1, speed=1, pan=0, amp=0.5, cawenvpeak=0.3, cawbpf=1150, cawbpq=0.33, cawhpf=550, cawhpq=0.05, cawformf=1600, cawformq=0.1, cawformgain=0.9, cawdist=0.4|
    var note, freq0, freq1, dur, env, mf, sig, bprq, formrq;
    note = freq.cpsmidi;
    freq0 = (freq*0.25) * speed;
    freq1 = 600 * (note - 60 * 0.5).midiratio * speed;
    dur = 0.5/(rate*speed);
    env = EnvGen.ar(Env.perc(cawenvpeak*dur, 1.0-cawenvpeak*dur), doneAction: Done.freeSelf) ** 0.3;
    mf = SinOsc.ar(voice.linexp(1, 0, 50, 80)).max(0) ** 0.5;
    sig = Saw.ar(env.linlin(0, 1, freq0, freq1) + (mf * env.linlin(0, 1, 325, 75)));
    bprq = cawbpq.linexp(0, 1, 1, 0.001);
    sig = BPF.ar(sig, cawbpf, bprq, bprq.sqrt.reciprocal);
    sig = RHPF.ar(sig, cawhpf*(note - 48 * 0.5).midiratio * speed, cawhpq.linexp(0, 1, 1, 0.001));
    formrq = cawformq.linexp(0, 1, 1, 0.001);
    sig = sig + (cawformgain * BPF.ar(sig, cawformf, formrq, formrq.sqrt.reciprocal));
    sig = LeakDC.ar(sig);
    sig = (sig * env * cawdist).tanh * 6 * amp;
    sig = Pan2.ar(sig, pan);
    Out.ar(out, DirtPan.ar(sig, ~dirt.numChannels, pan, env))
}).add;

why did i name things differently here? we may never know.

try a Tidal pattern like:

d1
  $ note "<0 12 24 -12 -24>*2"
  # s "supercaw"
  # speed (rangex 0.5 2 rand)
  # rate (rangex 0.5 2 $ fast 1.1 rand)
  # voice (fast 1.2 rand)