Ultra realistic snare drum synthesis

This thing blows my little mind, the wmd kraken, the creator says it’s all digital synthesis written in machine code, without any aid from online papers. Also proprietary. It’s amazingly accurate,
I wish I could do this in SC
Anyway, I think it’s impressive

Nice AB comparison with a real snare on this vid

2 Likes

i also came across this one the other day… really impressive! And i also thought how nice it would it be to build a synthdef that implements this techniques

2 Likes

Updated

Maybe if I mixed a little 909 snare in there it would sound like a real snare. Tell me if the code is off.


SynthDef(\realisticSnare, {
    arg out=0, amp=0.5, mul=1, pan=0,
        freq1=111, freq2=333, freq3=55, atck= 0.001, hrm = 7,
        transientAmp=1, transientFreq=200, transientDecay=0.01,
        drumHeadDelay=0.005, drumHeadFeedback=0.5, drumHeadGain=1,
        feedbackLoopTime=0.005, // Parameter for feedback loop time
        eqFreq1=500, eqQ1=1, eqGain1=0,
        eqFreq2=1000, eqQ2=1, eqGain2=0,
        eqFreq3=2000, eqQ3=1, eqGain3=0,
        reverbMix=0.2, reverbRoom=0.5, reverbDamp=0.5;

    var transient, drumHead, snare, reverb, harmonics;

    // Transient (Channel 1)
    transient = BrownNoise.ar(0.9) + WhiteNoise.ar(mul) * Env.perc(0.001, transientDecay).ar;
    transient = transient + Pulse.ar(transientFreq, 0.5, 1) * Env.perc(0.001, transientDecay * 0.5).ar;

    // Harmonics generation
    harmonics = Mix.new([
        Pulse.ar(freq1, 0.5, 0.33),
        Pulse.ar(freq2, 0.2, 0.33),
        Pulse.ar(freq3, 0.3, 0.33)
    ]);
	harmonics * hrm;

    transient = transient + (harmonics * Env.perc(atck, transientDecay * 2).ar);
    transient = transient * transientAmp;
    transient = transient * transientDecay;

    // Drum Head (Channel 2) with controllable feedback loop time
    drumHead = LocalIn.ar(1) + (transient * drumHeadGain);
    drumHead = DelayC.ar(drumHead, 1, feedbackLoopTime); // Control the feedback loop time
    drumHead = drumHead.tanh; // Soft limiting to prevent runaway
    LocalOut.ar(drumHead * drumHeadFeedback);

    // Apply EQ to the entire signal (transient + drum head)
    snare = Mix([transient, drumHead]);

    // Multiple EQ stages
    snare = BPeakEQ.ar(snare, eqFreq1, eqQ1, eqGain1);
    snare = BPeakEQ.ar(snare, eqFreq2, eqQ2, eqGain2);
    snare = BPeakEQ.ar(snare, eqFreq3, eqQ3, eqGain3);

    snare = LeakDC.ar(snare);

    // Reverb
    reverb = FreeVerb.ar(snare, reverbMix, reverbRoom, reverbDamp);

    Out.ar(out, Pan2.ar(reverb * amp, pan));
}).add;

// Example usage
(
Synth(\realisticSnare, [
    \amp, 0.9,
    \mul, 3,
    \transientAmp, 8,
    \transientFreq, 120,
    \freq1, 124,
    \freq2, 133,
    \freq3, 122,
	\hrm, 5,
	\atck, 0.04,
    \transientDecay, 0.2,
    \drumHeadFeedback, 0.39,
    \drumHeadGain, 0.8,
    \feedbackLoopTime, 0.005, // Adjust this to control the feedback loop time
    \eqFreq1, 1220,
    \eqQ1, 1,
    \eqGain1, 6,
    \eqFreq2, 1250,
    \eqQ2, 0.7,
    \eqGain2, -3,
    \eqFreq3, 200,
    \eqQ3, 0.5,
    \eqGain3, 3,
    \reverbMix, 0.5,
    \reverbRoom, 0.7,
    \reverbDamp, 0.8
]);
)

1 Like

And I added the an analogdrum Ugen, you’ll need that

Still not right, but its close I think

SynthDef(\realisticSnare, {
    arg out=0, amp=0.5, mul=1, pan=0, hpf =443, bss =5,
        freq1=111, freq2=333, freq3=55, atck= 0.001, hrm = 7, anaMul =3,
        transientAmp=1, transientDecay=0.01,
        drumHeadDelay=0.005, drumHeadFeedback=0.5, drumHeadGain=1,
        feedbackLoopTime=0.005, // Parameter for feedback loop time
        eqFreq1=500, eqQ1=1, eqGain1=0,
        eqFreq2=1000, eqQ2=1, eqGain2=0,
        eqFreq3=2000, eqQ3=1, eqGain3=0,
        reverbMix=0.2, reverbRoom=0.5, reverbDamp=0.5,
	     duration=1;

    var transient,bsdrm,overallEnv, springs, ana, drumHead, snare, reverb, harmonics;

    // Transient (Channel 1)
    transient = BrownNoise.ar(0.9) + WhiteNoise.ar(mul) * Env.perc(0.001, transientDecay).ar;
    transient = transient + Pulse.ar(233, 0.5, 1) * Env.perc(0.001, transientDecay * 0.5).ar;
	transient = HPF.ar(transient, FSinOsc.kr(1, 0, hpf, 4000), 5);
	springs = Mix.new([
	StringVoice.ar( transient, infsustain: 0.3, freq: Rand(200.0, 400.0),  accent: 0.3, structure: 0.5, brightness: 1, damping: 0.4),
	StringVoice.ar( transient, infsustain: 0.3, freq: Rand(200.0, 400.0),  accent: 0.3, structure: 0.5, brightness: 1, damping: 0.4),
		StringVoice.ar( transient, infsustain: 0.3, freq: Rand(200.0, 400.0),  accent: 0.3, structure: 0.5, brightness: 1, damping: 0.4)]);
    springs * Env.perc(0.001, transientDecay).ar;
    // Harmonics generation
    harmonics = Mix.new([
        Pulse.ar(freq1, 0.5, 0.33),
        Pulse.ar(freq2, 0.2, 0.33),
        Pulse.ar(freq3, 0.3, 0.33)
    ]);
	harmonics * hrm;
    bsdrm= AnalogBassDrum.ar(
		transient, infsustain: 0.3, accent: 0.9, freq: 22, tone: 0.3, decay: 0.2,
		attackfm: 0.1,selffm:0.2);
	bsdrm * bss;
	ana= AnalogSnareDrum.ar(transient, infsustain: 0.2, accent: 0.3, freq: 136, tone: 0.164885, decay: 0.3, snappy: 0.1311094)* anaMul * Env.perc(0.001, transientDecay).ar;


    transient = transient + (harmonics * Env.perc(atck, transientDecay * 2).ar).tanh;
    transient = transient * transientAmp;
    transient = transient * transientDecay;

    // Drum Head (Channel 2) with controllable feedback loop time
    drumHead = LocalIn.ar(1) + (transient * drumHeadGain * springs);
    drumHead = DelayC.ar(drumHead, 1, feedbackLoopTime); // Control the feedback loop time
    drumHead = drumHead.tanh; // Soft limiting to prevent runaway
    LocalOut.ar(drumHead * drumHeadFeedback);

    // Apply EQ to the entire signal (transient + drum head)
    snare = Mix([transient, drumHead, ana,bsdrm]);

    // Multiple EQ stages
    snare = BPeakEQ.ar(snare, eqFreq1, eqQ1, eqGain1);
    snare = BPeakEQ.ar(snare, eqFreq2, eqQ2, eqGain2);
    snare = BPeakEQ.ar(snare, eqFreq3, eqQ3, eqGain3);
	snare = Mix([snare, ana, bsdrm]) * 2;
    snare = LeakDC.ar(snare);

    // Reverb
    reverb = FreeVerb.ar(snare, reverbMix, reverbRoom, reverbDamp);
// Create an overall envelope
    overallEnv = EnvGen.kr(Env.linen(0.01, duration - 0.02, 2), doneAction: 2);

    // Apply the overall envelope to the final output
    reverb = reverb * overallEnv;


    Out.ar(out, Pan2.ar(reverb * amp, pan));
}).add;

// Example usage
(
Synth(\realisticSnare, [
    \amp, 7,
    \mul, 7,
    \transientAmp, 1,
    \hpf, 1300,
	\bss, 4,
    \freq1, 154,
    \freq2, 253,
    \freq3, 322,
    \anaMul, 2,
    \hrm, 3,
    \ack, 0.0024,
    \transientDecay, 0.28,
    \drumHeadFeedback, 0.009,
    \drumHeadGain, 0.09,
    \feedbackLoopTime, 0.001,
    \eqFreq1, 320,
    \eqQ1, 4,
    \eqGain1, 3,
    \eqFreq2, 350,
    \eqQ2, 125,
    \eqGain2, -4,
    \eqFreq3, 200,
    \eqQ3, 366,
    \eqGain3, 6,
    \reverbMix, 0.16,
    \reverbRoom, 0.4,
    \reverbDamp, 0.9,
    \duration, 1 // Set the duration to 1 second
]);
)
---
less bright

(
Synth(\realisticSnare, [
    \amp, 3,
    \mul, 1.9,
    \transientAmp, 1,
    \hpf, 1300,
	\bss, 6,
    \freq1, 154,
    \freq2, 253,
    \freq3, 322,
    \anaMul, 2,
    \hrm, 3,
    \ack, 0.26,
    \transientDecay, 0.3,
    \drumHeadFeedback, 0.01,
    \drumHeadGain, 1,
    \feedbackLoopTime, 0.02,
    \eqFreq1, 320,
    \eqQ1, 4,
    \eqGain1, 3,
    \eqFreq2, 1250,
    \eqQ2, 25,
    \eqGain2, -4,
    \eqFreq3, 100,
    \eqQ3, 166,
    \eqGain3, 6,
    \reverbMix, 0.26,
    \reverbRoom, 0.6,
    \reverbDamp, 1,
    \duration, 1 // Set the duration to 1 second
]);
)
----
(
Pbind(
    \instrument, \realisticSnare,
    \dur, 0.6,  // Play every 2 seconds
   \amp, 7,
    \mul, 7,
    \transientAmp, 1,
    \hpf, 1300,
	\bss, 4,
    \freq1, 154,
    \freq2, 253,
    \freq3, 322,
    \anaMul, 2,
    \hrm, 3,
    \ack, 0.0024,
    \transientDecay, 0.28,
    \drumHeadFeedback, 0.009,
    \drumHeadGain, 0.09,
    \feedbackLoopTime, 0.001,
    \eqFreq1, 320,
    \eqQ1, 4,
    \eqGain1, 3,
    \eqFreq2, 350,
    \eqQ2, 125,
    \eqGain2, -4,
    \eqFreq3, 200,
    \eqQ3, 366,
    \eqGain3, 6,
    \reverbMix, 0.16,
    \reverbRoom, 0.4,
    \reverbDamp, 0.9,
    \duration, 1 // Set the duration to 1 second
).play;
)

1 Like

I’ve given this video a go here. It’s not perfect, but I think it’s usable. Feedback welcome as always. JPverb seems to be a bit computationally intensive but it just sounds so much better than the alternatives in the class library, which I think is one area where DAWs just kill SC.

(
SynthDef(\snare, {
    var transient, resonance, snare;
    var sig;

    transient = WhiteNoise.ar + Pulse.ar(239, 0.3); // tweak freq to change pitch of transient
    transient = HPF.ar(transient, 120);
    transient = BPeakEQ.ar(transient, [300, 1000], 1, [1.1, 0.6]);
    transient = transient * Env.perc(0, 0.079).ar * 1.dbamp;
    
    snare = BPeakEQ.ar(WhiteNoise.ar, 2000, 1, 6.3) * Env.perc(0, 0.17).ar * -3.dbamp;
    snare = HPF.ar(snare, 300);

    resonance = transient + LocalIn.ar(1);
    resonance = DelayC.ar(resonance, 0.1, 0.01152); // tweak delay time to change pitch of the resonance
    resonance = HPF.ar(resonance, 400);
    resonance = LPF.ar(resonance, 3000);
    resonance = BPeakEQ.ar(resonance, 550, 1.3, -4.3);
    resonance = resonance * -0.11.dbamp; // tweak this to change length of resonance
    LocalOut.ar(resonance);

    resonance = resonance * -4.5.dbamp;

    
    sig = transient + resonance + snare ! 2; 
    sig = sig + JPverb.ar(sig * -20.dbamp).sum;
    sig = BPeakEQ.ar(sig, 900, 1, 2.5);
    sig = HPF.ar(sig, 150);
    sig = (sig * 1.6).tanh * 0.7;
    sig = sig * Env.perc(0, 0.7).ar(Done.freeSelf);
    sig = sig * -10.dbamp;
    Out.ar(0, sig);
}).add;
)
1 Like

Interesting. I mostly have experience using Logic, Protools and Ableton Live. I must admit that I very rarely use the reverbs native to these DAWs. I find Ableton to have the best built-in reverb of the three, still I almost always use 3rd party plugins. Which DAW reverb plugs do you like over SC (Class library or your own algos)?

Space designer (convolution) in Logic is probably good but the IRs are not nearly as good as e.g. Altiverb’s IMO. But I guess the fairer comparison is between algorithmic reverbs in any case.

1 Like

To clarify: I very rarely use DAWs, but the ease with which a stock reverb in the above video was packed into a snare drum patch was pretty great. Obviously we can now use VSTs in SuperCollider but it’d be pretty extreme to load Valhalla into a SynthDef just to make a snare drum sound…I think. I also forgot to try NHHall, though.

1 Like

The hybrid reverb from the ableton stock plugins is awesome, i mostly use its convolution engine with short impulse responses for colouring. I really dont like drained in reverb sounds. I additionally have the Fabfilter Pro-R 2. I have to admit everything which would need a single sample feedback loop, i dont do in SC.

2 Likes

Sounds good!
I think I might just have to buy the kraken and send it triggers from sc.
Im losing touch with my gear getting lost in sc.

1 Like

I love the metallic character of the synth. Maybe not that close to the realistic snare in the videos, but definitely a useful generator for percussion!

1 Like

Wow! this is awesome!
It is really flexible… tweaking here and there many cool snare sounds can be done with this…
I’ll try to wrap it up to make it usable in my workflow and will send you some results!

I agree with the reverb thought… i’ve been trying to make a useful reverb in SC for ages, and it is really difficult to achieve something that can be used both for short percussive sounds and at the same time for vocals, chords or more “smooth” sounds… i think there’s a whole recent thread about it.

I usually inject my SC synth outputs with blackhole to Reaper and do the postproduction stage there, mainly because of this reason… recording into tracks, mixing and slight mastering in the DAW. After 3 years of diving into SC, I’d love to be able to fully emancipate from the DAW, but for sound-design commissions it is still very useful given my poor skills…

I agree. It has a metallic sound to it when pushed, Maybe a bass drum in there would be good for some beef

Ive got actual rack effects. Old Eventide 1745m and a Marshall Time Modulator. It’s night and day. I ran some beats I made in SC through the Eventide and it was incredible. I couldn’t believe it. The best VST reverb Ive heard is the EMT 250 plug in.
Quadraverbs are cheap I should get one of those. Sc’s strength is that I enjoy mucking about with it. Maybe it’s FFT stuff and the Pattern system too. Def the Patterns are cool. But I guess CDP is better for FFT. I don’t know. Id be interested in hear what others like about SC.

I don’t try and make a computer sound analog or like hardware, I use a computer to be really digital sounding or control things with it. Use its strengths. Maybe the Flucoma thing will be good.
But, if you have other things going mixed with SC that are hardware, and have some actual analog saturation and grit, the SC stuff will sit very well in a mix.

I don’t think the Kraken is using reverb. Delays maybe. I think he mentioned delays (He wont tell me much. )

Why not? Just curious

updated it with the AnalogBassDrum Ugen.

In all creative coding enviroments like SC, Max, Pd audio samples are handled in chunks / blocks for performance reasons. In SC the number of samples in these chunks / blocks are defined by the blocksize. In SC your blocksize is typically set to 64 samples. When using LocalIn / LocalOut or set up a circular buffer with BufRd / BufWr to create a feedback loop and having set your blocksize to 64 samples, you introduce a delay of 64 samples into your feedback path.
You can have a lot of fun doing this and also learn alot about dsp :slight_smile:

But for alot of audio processing like filter design or delay based effects this is undesirable. These need sample by sample treatment, which could be done in C++, Faust or gen~.

1 Like

I had a kraken for a while. Great module. I connected the es-8 to it and made thousands of samples from random settings. Now I can load those into FluCoMa and I have a library of samples I can sort in various ways.

Sam

2 Likes

Oh I see, that needs to be fixed, why can’t sc have this as well.? how’s gen work in max? Is it separate from the main app (max msp) ? Thanks

Those samples available? I understand if they aren’t. I’ll have to try this, Did you set up a TExpRandi on all the inputs and hit record and let it rip?

I’m curious how you set up FluCoMa to use these samples. . Sounds like what I’m after. Do you use patterns ? Thanks

Nobody disagrees with you – it’s just that somebody has to do it. Nobody is getting paid here, so, somebody has to volunteer to do it. By contrast, Cycling 74 could take some chunk of their high license fees and assign a few developers to spend seven years creating gen, gen~ and jit.gen. (I don’t have the citation handy, but I saw a speech by David Zicarelli online where he said that’s how long it took.)

It would be nice to be able to assign a different block size to a Synth node. That would be a much smaller dev effort than gen (analogous to block~ in Pure Data).

hjh

2 Likes