«audrey II» by gosub
on 07 Feb'26 11:45 inTo start hearing something, raise the FbGain level above 0dB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
// patch name: Audrey II // patch date: 2026-02-06 // patch desc: software Audrey II drone synthesizer (Synthux Academy / Fede Repic) // feedback-driven self-oscillating drone machine // // signal flow: // noise seed (-90dBFS) + fb_return -> KS resonator -> overdrive -> LPF -> HPF -> reverb // ^ | // +--- feedback delay ("body", 1-100ms, stereo decorrelated) <--- fb_gain <----+ // | // echo send // v // echo delay (50ms-5s) // BPF 800Hz -> tanh // (tape degradation) // // no oscillator generates sound -- the feedback loop self-excites when gain > ~0 dB ( SynthDef(\audrey2, { |out=0, freq=48, fbGain= -20, body=0.01, lpf=12000, hpf=60, verbMix=0.3, verbDecay=0.5, echoSend=0, echoTime=0.3, echoFb=0.5, vol=0.3| var seed, sigL, sigR, verbL, verbR; var fbRetL, fbRetR, echoRetL, echoRetR; var echoTapeL, echoTapeR, echoOutL, echoOutR; var kFreq = Lag.kr(freq, 0.2).midicps; var kBody = Lag.kr(body, 1.0); var kFbAmp = Lag.kr(fbGain, 0.05).dbamp; var kLpf = Lag.kr(lpf, 0.05); var kHpf = Lag.kr(hpf, 0.05); var kEchoTime = Lag.kr(echoTime, 0.5); var kEchoSend = Lag.kr(echoSend, 0.05); var kEchoFb = Lag.kr(echoFb, 0.05); // feedback return: 2 main fb + 2 echo fb #fbRetL, fbRetR, echoRetL, echoRetR = LocalIn.ar(4); // === MAIN FEEDBACK LOOP === // white noise seed at -90 dBFS + feedback (independent L/R seeds) sigL = WhiteNoise.ar(-90.dbamp) + (fbRetL * kFbAmp); sigR = WhiteNoise.ar(-90.dbamp) + (fbRetR * kFbAmp); // karplus-strong resonator (tuned comb filter + brightness damping) // decay matches original's 0.8 damping factor: ~31 periods to -60dB sigL = OnePole.ar(CombL.ar(sigL, 0.2, kFreq.reciprocal, kFreq.reciprocal * 31), 0.98); sigR = OnePole.ar(CombL.ar(sigR, 0.2, kFreq.reciprocal, kFreq.reciprocal * 31), 0.98); // overdrive (soft clipping) sigL = (sigL * 1.5).tanh; sigR = (sigR * 1.5).tanh; // feedback loop filters + DC blocker sigL = LeakDC.ar(HPF.ar(LPF.ar(sigL, kLpf), kHpf)); sigR = LeakDC.ar(HPF.ar(LPF.ar(sigR, kLpf), kHpf)); // reverb (inside the feedback loop, as in original) #verbL, verbR = FreeVerb2.ar(sigL, sigR, Lag.kr(verbMix, 0.05), Lag.kr(verbDecay, 0.05), 0.5); // === ECHO DELAY (outside the feedback loop) === // tape-style: each repetition passes through BPF + soft clip, // progressively losing highs and lows (telephone-like degradation) // tape degradation on echo feedback return echoTapeL = BPF.ar(echoRetL, 800, 1.0).tanh; echoTapeR = BPF.ar(echoRetR, 800, 1.0).tanh; // mix echo input (dry send) with degraded feedback, then delay echoOutL = DelayC.ar((verbL * kEchoSend) + (echoTapeL * kEchoFb), 5, kEchoTime); echoOutR = DelayC.ar((verbR * kEchoSend) + (echoTapeR * kEchoFb), 5, kEchoTime); // write all feedback paths LocalOut.ar([ // main feedback delay ("body") -- right offset by 4 samples for stereo DelayC.ar(verbL, 0.25, kBody), DelayC.ar(verbR, 0.25, max(SampleDur.ir, kBody - (4 * SampleDur.ir))), // echo delay feedback echoOutL, echoOutR ]); // final mix: dry + echo wet, then limiter Out.ar(out, Limiter.ar([ verbL + echoOutL, verbR + echoOutR ] * 0.5 * Lag.kr(vol, 0.05), 0.7)); }).add; ) ( a = Synth(\audrey2); w = Window.new("Audrey II", Rect(200, 200, 460, 480)).layout_( VLayout( StaticText().string_("Audrey II -- feedback drone synthesizer").align_(\center), HLayout( VLayout(StaticText().string_("Freq"), Slider().value_([16,72].asSpec.unmap(48)) .action_({|x| a.set(\freq, [16,72].asSpec.map(x.value))})), VLayout(StaticText().string_("Fb Gain"), Slider().value_([-60,12].asSpec.unmap(-20)) .action_({|x| a.set(\fbGain, [-60,12].asSpec.map(x.value))})), VLayout(StaticText().string_("Body"), Slider().value_([0.001,0.1,\exp].asSpec.unmap(0.01)) .action_({|x| a.set(\body, [0.001,0.1,\exp].asSpec.map(x.value))})), ), HLayout( VLayout(StaticText().string_("LPF"), Slider().value_([100,18000,\exp].asSpec.unmap(12000)) .action_({|x| a.set(\lpf, [100,18000,\exp].asSpec.map(x.value))})), VLayout(StaticText().string_("HPF"), Slider().value_([10,4000,\exp].asSpec.unmap(60)) .action_({|x| a.set(\hpf, [10,4000,\exp].asSpec.map(x.value))})), ), HLayout( VLayout(StaticText().string_("Verb Mix"), Slider().value_(0.3) .action_({|x| a.set(\verbMix, x.value)})), VLayout(StaticText().string_("Verb Decay"), Slider().value_([0.2,1.0].asSpec.unmap(0.5)) .action_({|x| a.set(\verbDecay, [0.2,1.0].asSpec.map(x.value))})), ), HLayout( VLayout(StaticText().string_("Echo Send"), Slider().value_([0.001,1.0,\exp].asSpec.unmap(0.001)) .action_({|x| a.set(\echoSend, [0.001,1.0,\exp].asSpec.map(x.value))})), VLayout(StaticText().string_("Echo Time"), Slider().value_([0.05,5.0,\exp].asSpec.unmap(0.3)) .action_({|x| a.set(\echoTime, [0.05,5.0,\exp].asSpec.map(x.value))})), VLayout(StaticText().string_("Echo Fb"), Slider().value_([0.0,1.5].asSpec.unmap(0.5)) .action_({|x| a.set(\echoFb, [0.0,1.5].asSpec.map(x.value))})), ), HLayout( VLayout(StaticText().string_("Volume"), Slider().value_([0.001,1.0,\exp].asSpec.unmap(0.3)) .action_({|x| a.set(\vol, [0.001,1.0,\exp].asSpec.map(x.value))})), ), ) ).front; )
reception
comments