b = Buffer.read(s, "/home/lcoogan/snd/demos/springverb.wav")

s.prepareForRecord;
s.record("~/snd/releases/desolation-mountain/springverb.wav");

(
s.waitForBoot {
	s.record(
		"~/snd/releases/desolation-mountain/springverb.wav",
		2
	);
};
)

s.stopRecording;

(
{
    PlayBuf.ar(2, b, 1, loop: 0) * 0.3
}.play;
)

(
~echo = Synth(\springverb, [
    \length, TempoClock.default.tempo * (3/8),
    \fb, 0.1,
    \sep, 0.0014
], addAction: \addToTail);
)

(
~echo.free;
~springverb.free;
)

(
~springverb = Synth(\springverb, [
    \decay, 1.8,
    \boing, 0.025,
    \mix, 0.5,
    \tone, 3000,
    \drive, 1.2
], addAction: \addToTail);
)

(
~springverb = Synth(\springverb, [
    \decay, 1.8,
    \boing, 0.025,
    \mix, 0.5,
    \tone, 3000,
    \drive, 1.2
], addAction: \addToTail);

(
~echo = Synth(\springverb, [
    \length, TempoClock.default.tempo * (3/8),
    \fb, 0.1,
    \sep, 0.0014
], addAction: \addToTail);
)
)



(
SynthDef(\echo, { |length = 1, fb = 0.8, sep = 0.012|
    var input = In.ar(0, 2);
    var output = input + Fb({ |feedback|

        var left, right, spring, magic;
        magic = LeakDC.ar(feedback * fb + input);
        magic = HPF.ar(magic, 400);
        magic = LPF.ar(magic, 5000);
        magic = magic.tanh;

        // Simulate spring reverb inside the feedback loop
        spring = CombL.ar(magic, 0.1, 0.03, 1.5); // short decay, boingy
        spring = AllpassL.ar(spring, 0.1, [0.022, 0.027], 1.5);
        magic = magic + spring * 0.4; // mix in some splash

        #left, right = magic;
        magic = [
            DelayC.ar(left, 1, LFNoise2.ar(12).range(0, sep)),
            DelayC.ar(right, 1, LFNoise2.ar(12).range(sep, 0))
        ];

    }, length);
    ReplaceOut.ar(0, output);
}).store;
)




(
SynthDef(\springverb, { |inBus = 0, outBus = 0, decay = 1.2, boing = 0.03, mix = 0.4, tone = 5000, drive = 1.0|
    var dry = In.ar(inBus, 2);
    var verb, spring, wet;

    // Pre-emphasize and drive the input (mimics spring preamp)
    spring = dry * drive;
    spring = spring.tanh;

    // Simulate springy tail
    spring = CombL.ar(spring, 0.1, boing, decay);
    spring = AllpassL.ar(spring, 0.1, [0.025, 0.030], decay);
    spring = LPF.ar(spring, tone);  // darken the tail
    spring = spring * mix;

    // Mix dry and wet
    verb = XFade2.ar(dry, spring, mix * 2 - 1); // Crossfade between dry and wet

    Out.ar(outBus, verb);
}).store;
)
