( SynthDef(\sin, { |out, sustain = 1, freq = 440, speed = 1, begin=0, end=1, pan, accelerate| var env, sound, rate, phase, amp; amp = AmpCompA.kr(freq); env = EnvGen.ar(Env.perc(0.002, sustain, 1, -1), doneAction:2); phase = Line.ar(begin, end, sustain); rate = speed + Sweep.kr(1, accelerate); sound = SinOsc.ar(freq); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env) ) }).add ); // physical modeling of a vibrating string, using a delay line (CombL) excited by an intial pulse (Impulse) // To make it a bit richer, I've combined two slightly detuned delay lines // "accelerate" is used for a pitch glide, and "sustain" changes the envelope timescale ( SynthDef(\supermandolin, {|out, sustain=1, pan, accelerate, freq, detune=0.2, speed=1| var env = EnvGen.ar(Env.linen(0.002, 0.996, 0.002, 1,-3), timeScale:sustain, doneAction:2); var sound = Decay.ar(Impulse.ar(0,0,0.1), 0.1*(freq.cpsmidi)/69) * WhiteNoise.ar; var pitch = freq * DirtFreqScale.kr(speed, accelerate, sustain); sound = CombL.ar(sound, 0.05, pitch.reciprocal*(1-(detune/100)), sustain) + CombL.ar(sound, 0.05, pitch.reciprocal*(1+(detune/100)), sustain); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // an example of additive synthesis, building up a gong-like noise from a sum of sine-wave harmonics // notice how the envelope timescale and amplitude can be scaled as a function of the harmonic frequency // "voice" provides something like a tone knob, and "decay" adjusts how the harmonics decay // as in the other SynthDefs, "sustain" affects the overall envelope timescale and "accelerate" for pitch glide // for a demo, try this in Tidal // d1 $ n (slow 2 $ fmap (*7) $ run 8) # s "supergong" # decay "[1 0.2]/4" # voice "[0.5 0]/8" ( SynthDef(\supergong,{|out, sustain=1, pan, accelerate, freq, voice=0, decay=1, speed=1| // lowest modes for clamped circular plate var freqlist =[1.000, 2.081, 3.414, 3.893, 4.995, 5.954, 6.819, 8.280, 8.722, 8.882, 10.868, 11.180, 11.754, 13.710, 13.715, 15.057, 15.484, 16.469, 16.817, 18.628]**1.0; var tscale = 100.0 / freq / (freqlist**(2-clip(decay,0,2))); var ascale =freqlist**clip(voice,0,4); var sound = Mix.arFill(15, {arg i; EnvGen.ar(Env.perc(0.01*tscale[i], 0.5*tscale[i], 0.2*ascale[i] ), timeScale:sustain*5) * SinOsc.ar(freq * freqlist[i] * DirtFreqScale.kr(speed, accelerate, sustain))}); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)) }).add ); // hooking into a nice synth piano already in supercollider // uses the "velocity" parameter to affect how hard the keys are pressed // "sustain" controls envelope and decay time ( SynthDef(\superpiano,{|out, sustain=1, pan, velocity=1, detune=0.1, muffle=1, stereo=0.2, freq=440, accelerate=0, speed=1| var env = EnvGen.ar(Env.linen(0.002, 0.996, 0.002, 1,-3), timeScale:sustain, doneAction:2); // the +0.01 to freq is because of edge case rounding internal to the MdaPiano synth var sound = MdaPiano.ar(freq*DirtFreqScale.kr(speed, accelerate, sustain)+0.01, vel:velocity*100, hard:0.8*velocity, decay:0.1*sustain, tune:0.5, random:0.05, stretch:detune, muffle:0.8*muffle, stereo:stereo); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // waveguide mesh, hexagonal drum-like membrane ( SynthDef(\superhex,{|out, rate=1, sustain=1, pan, freq, accelerate, speed=1| var env = EnvGen.ar(Env.linen(0.02, 0.96, 0.02, 1,-3), timeScale:sustain, doneAction:2); var tension = 0.05*freq/400 * DirtFreqScale.kr(speed, accelerate, sustain); var loss = 1.0 - (0.01 * rate / freq); var sound = MembraneHexagon.ar(Decay.ar(Impulse.ar(0,0,1), 0.01), tension, loss); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // Kick Drum using Rumble-San's implementation as a starting point // http://blog.rumblesan.com/post/53271713518/drum-sounds-in-supercollider-part-1 // "n" controls the kick frequency in a nonstandard way // "sustain" affects overall envelope timescale, "accelerate" sweeps the click filter freq, // "pitch1" affects the click frequency, and "decay" changes the click duration relative to the overall timescale ( SynthDef(\superkick, {|out, sustain=1, pan, accelerate, n, pitch1=1, decay=1, speed=1| var env, sound, dur, clickdur; env = EnvGen.ar(Env.linen(0.01, 0, 0.5, 1, -3), timeScale:sustain, doneAction:2); sound = SinOsc.ar((n - 25.5).midicps); clickdur = 0.02*sustain*decay; sound = sound + (LPF.ar(WhiteNoise.ar(1), 1500*pitch1*DirtFreqScale.kr(speed, accelerate, clickdur) ) * Line.ar(1, 0, clickdur)); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // A vaguely 808-ish kick drum // "n" controls the chirp frequency, "sustain" the overall timescale, "rate" the filter sweep speed, // and "voice" the sinewave feedback ( SynthDef(\super808, {|out, rate=1, sustain=1, pan, voice=0, n, speed=1, accelerate| var env, sound, freq; n = ((n>0)*n) + ((n<1)*3); freq = (n*10).midicps * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.linen(0.01, 0, 1, 1, -3), timeScale:sustain, doneAction:2); sound = LPF.ar(SinOscFB.ar(XLine.ar(freq.expexp(10, 2000, 1000, 8000), freq, 0.025/rate), voice), 9000); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // Hi-hat using Rumble-San's implementation as a starting point // http://blog.rumblesan.com/post/53271713518/drum-sounds-in-supercollider-part-1 // using "n" in a weird way to provide some variation on the frequency // "sustain" affects the overall envelope rate, "accelerate" sweeps the filter ( SynthDef(\superhat, {|out, sustain=1, pan, accelerate, n, speed=1| var env, sound, freq; env = EnvGen.ar(Env.linen(0.01, 0, 0.3, 1, -3), timeScale:sustain, doneAction:2); freq = 2000 * DirtFreqScale.kr(speed, accelerate, sustain) * (n/5 + 1).wrap(0.5,2); sound = HPF.ar(LPF.ar(WhiteNoise.ar(1), 3*freq), freq); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // Snare drum using Rumble-San's implementation as a starting point // http://blog.rumblesan.com/post/53271713909/drum-sounds-in-supercollider-part-2 // again using "n" for some variation on frequency, "decay" for scaling noise duration relative to tonal part // "sustain" for overall timescale, "accelerate" for tonal glide ( SynthDef(\supersnare, {|out, sustain=1, pan, accelerate, n, decay=1, speed=1| var env = EnvGen.ar(Env.linen(0.01, 0, 0.6, 1, -3), timeScale:sustain, doneAction:2); var freq = 100 * DirtFreqScale.kr(speed, accelerate, sustain) * (n/5+1).wrap(0.5,2); var sound = LPF.ar(Pulse.ar(freq), Line.ar(1030, 30, 0.2*sustain)) + (BPF.ar(HPF.ar(WhiteNoise.ar(1), 500), 1500) * Line.ar(1, 0, 0.2*decay)); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // Hand clap using Rumble-San's implementation as a starting point // http://blog.rumblesan.com/post/53271713909/drum-sounds-in-supercollider-part-2 // "delay" controls the echo delay, "rate" will affect the decay time, "n" changes how spread is calculated // "pitch1" will scale the bandpass frequency, and "sustain" the overall timescale ( SynthDef(\superclap, {|out, rate=1, sustain=1, pan, n, delay=1, pitch1=1 | var env, sound; var spr = 0.005 * delay; env = EnvGen.ar(Env.linen(0.01, 0, 0.6, 1, -3), timeScale:sustain, doneAction:2); sound = BPF.ar(LPF.ar(WhiteNoise.ar(1), 7500*pitch1), 1500*pitch1); sound = Mix.arFill(4, {arg i; sound * 0.5 * EnvGen.ar(Env.new([0,0,1,0],[spr*(i**(n.clip(0,5)+1)),0,0.04/rate]))}); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // a controllable synth siren, defaults to 1 second, draw it out with "sustain" ( SynthDef(\supersiren, {|out, sustain=1, pan, freq, accelerate, speed=1| var env, sound; freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.linen(0.05, 0.9, 0.05, 1, -2), timeScale:sustain, doneAction:2); sound = VarSaw.ar(freq * (1.0 + EnvGen.kr(Env.linen(0.25,0.5,0.25,3,0), timeScale:sustain, doneAction:2)), 0, width:Line.kr(0.05,1,sustain)); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // The next four synths respond to the following parameters in addition to gain, pan, n, and all the "effect" parameters // (including attack, hold, and release). Default values in parentheses. // // sustain - scales overall duration // decay(0) - amount of decay after initial attack // accelerate(0) - pitch glide // semitone(12) - how far off in pitch the secondary oscillator is (need not be integer) // pitch1(1) - filter frequency scaling multiplier, the frequency itself follows the pitch set by "n" // rate(1)- LFO rate // lfo(1) - how much the LFO affects the filter frequency // resonance(0.2) - filter resonance // voice(0.5) - depends on the individual synth // a moog-inspired square-wave synth; variable-width pulses with filter frequency modulated by an LFO // "voice" controls the pulse width (exactly zero or one will make no sound) ( SynthDef(\supersquare, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq, voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2); var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var basefreq2 = basefreq / (2**(semitone/12)); var lfof1 = min(basefreq*10*pitch1, 22000); var lfof2 = min(lfof1 * (lfo + 1), 22000); var sound = (0.7 * Pulse.ar(basefreq, voice)) + (0.3 * Pulse.ar(basefreq2, voice)); sound = MoogFF.ar( sound, SinOsc.ar(basefreq/64*rate, 0).range(lfof1,lfof2), resonance*4); sound = sound.tanh * 2; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // a moog-inspired sawtooth synth; slightly detuned saws with triangle harmonics, filter frequency modulated by LFO // "voice" controls a relative phase and detune amount ( SynthDef(\supersaw, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq, voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2); var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var basefreq2 = basefreq * (2**(semitone/12)); var lfof1 = min(basefreq*10*pitch1, 22000); var lfof2 = min(lfof1 * (lfo + 1), 22000); var sound = MoogFF.ar( (0.5 * Mix.arFill(3, {|i| SawDPW.ar(basefreq * ((i-1)*voice/50+1), 0)})) + (0.5 * LFTri.ar(basefreq2, voice)), LFTri.ar(basefreq/64*rate, 0.5).range(lfof1,lfof2), resonance*4); sound = sound.tanh*2; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // a moog-inspired PWM synth; pulses multiplied by phase-shifted pulses, double filtering with an envelope on the second // "voice" controls the phase shift rate ( SynthDef(\superpwm, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq, voice=0.5, semitone=12, resonance=0.2, lfo=1, pitch1=1, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2); var env2 = EnvGen.ar(Env.pairs([[0,0.1],[0.1,1],[0.4,0.5],[0.9,0.2],[1,0.2]], -3), timeScale:sustain/rate); var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var basefreq2 = basefreq / (2**(semitone/12)); var lfof1 = min(basefreq*10*pitch1, 22000); var lfof2 = min(lfof1 * (lfo + 1), 22000); var sound = 0.7 * PulseDPW.ar(basefreq) * DelayC.ar(PulseDPW.ar(basefreq), 0.2, Line.kr(0,voice,sustain)/basefreq); sound = 0.3 * PulseDPW.ar(basefreq2) * DelayC.ar(PulseDPW.ar(basefreq2), 0.2, Line.kr(0.1,0.1+voice,sustain)/basefreq) + sound; sound = MoogFF.ar(sound, SinOsc.ar(basefreq/32*rate, 0).range(lfof1,lfof2), resonance*4); sound = MoogFF.ar(sound, min(env2*lfof2*1.1, 22000), 3); sound = sound.tanh*5; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // "voice" scales the comparator frequencies, higher values will sound "breathier" ( SynthDef(\supercomparator, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq, voice=0.5, resonance=0.5, lfo=1, pitch1=1, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.05,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -3), timeScale:sustain, doneAction:2); var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = VarSaw.ar(basefreq, 0, Line.ar(0,1,sustain)); var freqlist =[ 1.000, 2.188, 5.091, 8.529, 8.950, 9.305, 13.746, 14.653, 19.462, 22.003, 24.888, 25.991, 26.085, 30.509, 33.608, 35.081, 40.125, 42.023, 46.527, 49.481]**(voice/5); sound = Splay.arFill(16, {|i| sound > LFTri.ar(freqlist[i])}, 1); sound = MoogFF.ar( sound, pitch1 * 4 * basefreq + SinOsc.ar(basefreq/64*rate, 0, lfo*basefreq/2) + LFNoise2.ar(1,lfo*basefreq), LFNoise2.ar(0,0.1,4*resonance)); Out.ar(out, DirtPan.ar(0.5*sound, ~dirt.numChannels, pan, env)); }).add ); // uses the Atari ST emulation UGen with 3 oscillators // "slide" is for a linear frequency glide that will repeat "rate" times (can be fractional or negative) // "accelerate" is for an overall glide, // "pitch2" and "pitch3" control the ratio of harmonics // "voice" causes variations in the levels of the 3 oscillators ( SynthDef(\superchip, {|out, sustain=1, pan, freq, rate=1, slide=0, pitch2=2, pitch3=3, accelerate, voice=0, speed=1| var env, basefreq, sound, va, vb, vc; env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01,1,-1), timeScale:sustain, doneAction:2); basefreq = freq + wrap2(slide * 100 * Line.kr(-1,1+(2*rate-2),sustain), slide * 100); basefreq = basefreq * DirtFreqScale.kr(speed, accelerate, sustain); va = (voice < 0.5) * 15; vb = ((2*voice) % 1 < 0.5) * 15; vc = ((4*voice) % 1 < 0.5) * 15; sound= AY.ar( AY.freqtotone(basefreq), AY.freqtotone(pitch2*basefreq), AY.freqtotone(pitch3*basefreq), vola:va, volb:vb, volc:vc)/2; sound = tanh(sound)*2; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // digital noise in several flavors with a bandpass filter // "voice" at 0 is a digital noise for which "n" controls rate, at 1 is Brown+White noise for which "n" controls knee frequency // "accelerate" causes glide in n, "rate" will cause it to repeat // "pitch1" scales the bandpass frequency (which tracks "n") // "slide" works like accelerate on the bandpass // "resonance" is the filter resonance ( SynthDef(\supernoise, {|out, sustain=1, pan, freq, accelerate, slide=0, pitch1=1, rate=1, resonance=0, voice=0| var env, basefreq, sound, ffreq, acc; env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01,1,-1), timeScale:sustain, doneAction:2); acc = accelerate * freq * 4; basefreq = freq * 8 + wrap2(acc* Line.kr(-1,1+(2*rate-2), sustain), acc); ffreq = basefreq*5*pitch1* Line.kr(1,1+slide, sustain); ffreq = clip(ffreq, 60,20000); sound = XFade2.ar( LFDNoise0.ar(basefreq.min(22000), 0.5), XFade2.ar(BrownNoise.ar(0.5), WhiteNoise.ar(0.5), basefreq.cpsmidi/127), 2*voice-1); sound = HPF.ar(BMoog.ar(sound, ffreq, resonance, 3), 20); sound = clip(sound, -1,1) * 0.3; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // tuning fork // from my own experimentation and from "On the acoustics of tuning forks", Rossing Russell and Brown ( SynthDef(\superfork, {|out, sustain=1, pan, freq, accelerate=0, speed=1| var sound, env; freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.linen(0.001, 0.998, 0.001), timeScale:sustain, doneAction:2); sound = 0.2 * SinOsc.ar([1.0, 6.1, 16.7, 20.1] * freq) * XLine.ar([0.3, 1, 1.3, 2], [1e-4, 1e-7, 1e-6, 1e-7], sustain*[4,4,0.5,0.333]); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // hammond B3 sim // freq adjustments courtesy Tom Wiltshire (electricdruid.net) // drawbar settings selectable with "voice" and from many public domain sources, // Google "Hammond drawbar settings" and add your own in the big SelectX block // "perc" "percf" and "decay" are an attempt at the percussion, no idea if it sounds at all reasonable // vintage Hammonds had percf as 2 or 3 (switchable), two perc levels (maybe roughly 0.7 and 1.2?), // and two decay options (roughly 0 and maybe 1ish?) // "vibrato", "vrate", "perc", "percf" are all new params you'll need to define in Tidal if you want to change them ( SynthDef(\superhammond, {|out, sustain=1, decay=0, pan, freq, vibrato=0.5, vrate=7, voice=0, perc=0, percf=2, accelerate=0, speed=1| var freqs, amps, sound, click, env, ampscale, attrel; attrel = (sustain/2).clip(0,0.005); freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.linen(attrel, sustain-(2*attrel), attrel), doneAction:2); freqs = [0.5, 1.4988, 1, 2, 2.9976, 4, 5.0409, 5.9953, 8] * freq; freqs = 2**(freqs < 63) * freqs; // fold up bottom register freqs = freqs / (2**(freqs > 6000)); // fold down high harmonics freqs = freqs / (2**(freqs > 6000)); // do it again for the really high notes amps = SelectX.kr(voice, #[ [1, 4, 5, 4, 3, 1, 0, 0, 0], // 0: bass violin 16' [0, 0, 8, 0, 4, 0, 0, 0, 0], // 1: tibia 8' [0, 7, 8, 1, 2, 0, 0, 0, 0], // 2: bassoon 8' [0, 0, 7, 8, 8, 8, 8, 7, 2], // 3: french trumpet 8' [4, 0, 5, 5, 4, 5, 3, 3, 6], // 4: string ensemble [8, 8, 5, 3, 2, 4, 5, 8, 8], // 5: Blues [8, 8, 8, 0 ,0, 0, 0, 0, 3], // 6: Jazz 1 [8, 8, 8, 8, 8, 8, 8, 8, 8], // 7: Full Shout [8, 0, 0, 0, 0, 0, 8, 8, 8], // 8: Bro' Jack [0, 0, 8, 8, 0, 0, 0, 0, 0] // 9: Jazz 2 ]); amps = amps - [0, 0, 0, 0, 0, 0, 0.5, 1, 1.5]; // damp brilliance a bit amps = 2**(amps-8); click = WhiteNoise.ar(1) * XLine.ar(1,1e-6, 0.1); sound = 0.5 * Mix.ar( SinOsc.ar(freqs*(2*click+1), (2pi ! 9).rand, amps/amps.sum) ); sound = perc * 0.5 * SinOsc.ar(freq*percf, 2pi.rand) * XLine.ar(1,1e-6,2*decay+1) + sound; sound = sound + BAllPass.ar(sound, 1000*LFTri.kr(vrate,0,vibrato/2,1)); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // vibraphone simulation, adapted with some help from Kevin Larke's thesis Real Time Vibraphone Pitch and Timbre Classification // "decay" - use larger values to damp higher harmonics (default 0) // "velocity" - higher velocity will brighten the sound a bit (default 1) // "accelerate" - for a linear pitch bend // "modamp" - amplitude of the tremolo (0-2 is OK, default 1) // "modfreq" - frequency of the tremolo (default 7) // "detune" - adjusts a high harmonic to give the sound a different character ( SynthDef(\supervibe, {|out, sustain=1, decay=0, pan, freq, accelerate=0, velocity=1, modamp=1, modfreq=7.0, detune=0, speed=1| // most envelope shaping is done with XLines later, this envelope is just to clean up overall var env = EnvGen.ar(Env.linen(0.001, 0.998, 0.001), timeScale:sustain, doneAction:2); var sound, mod, freqs, hifreqs, decays; freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); freqs = freq * [1, 4, 10, 13.75 + detune]; hifreqs = freq * [19.2, 20, 21.2]; mod = SinOsc.kr(modfreq, Rand(0,2pi)).range(1-([0.5,0.3,0.3,0.5]*modamp),1); sound = 0.3 * [1, 1.1*velocity, 0.6*velocity*velocity, 0.5*velocity] * SinOsc.ar(freqs); decays = [1, 0.7*exp(-1.0*decay), 0.5*exp(-1.0*decay), 0.4*exp(-1.0*decay)]; sound = XLine.ar(1e-6, 1, 1/freqs) * XLine.ar(1, 1e-6, decays*4*sustain) * sound * mod; // main attacks and decays sound = (XLine.ar(0.3*(velocity+1e-6),1e-6,0.02) * SinOsc.ar(hifreqs)).sum + sound.sum; // hi frequency onset Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); // Hoover, adapted from Wouter Snoei's // http://superdupercollider.blogspot.com/2009/06/more-dominator-deconstruction.html // "slide" is used for the amount of initial pitch glide, positive slides up in pitch, negative slides down // also responds to "decay" for a different envelope shape and "accelerate" for constant pitch glide // uncomment the two lines with "rrand" for a different every time you evaulate it ( SynthDef(\superhoover, {|out, sustain=1, decay=0, pan, freq, accelerate=0, slide=0, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.03,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2); var pwm, mix, fglide; fglide = EnvGen.ar(Env.perc(0.05, 0.3, 1, \lin), timeScale:sustain) * (-1*slide/4) + 1; freq = freq * fglide * DirtFreqScale.kr(speed, accelerate, sustain); freq = SinOsc.kr( [2.94, 3.0, 3.07], [3.0, 5.5, 1.2] ).exprange(0.995, 1.005) * freq; // freq = SinOsc.kr( {2.9 rrand: 3.1}!3, {2pi.rand}!3 ).exprange(0.995, 1.005) * freq; pwm = SinOsc.kr( [1.3, 2.9, 4.4] ).range(1/8, 7/8); // pwm = SinOsc.kr( {1.0 rrand: 5.0}!3 ).range(1/8, 7/8); mix = ([1,0.9,1.1]*LFSaw.ar(freq*[0.25, 0.5, 1], [1, 1.01, 1.02]).range(0,1) * (1 - LFPulse.ar(freq*[0.5,1,2], [0,0,0], pwm))).sum * 0.15; mix = mix + LFPar.ar(freq * 0.25, 0, 0.1).sum; mix = BPeakEQ.ar(mix, 6000, 1, 3); mix = BPeakEQ.ar(mix, 3500, 1, 6); mix = mix.dup + CombC.ar(mix.dup, 1/200, SinOsc.kr(3, [0.5pi, 1.5pi]).range(1/300, 1/200), 0); Out.ar(out, DirtPan.ar(1.4*mix, ~dirt.numChannels, pan, env)); }).add ); // phased saws // "decay" and "accelerate" used as in some synths above, for envelope shaping and pitch bend, respectively // "slide" here is how fast it moves through the phase (default 1) // "detune" is for oscillator detuning and defaults to 1 ( SynthDef(\superzow, {|out, sustain=1, pan, accelerate, freq, decay=0, slide=1, detune=1, speed=1| var env = EnvGen.ar(Env.pairs([[0,0],[0.07,1],[0.2,1-decay],[0.95,1-decay],[1,0]], -1), timeScale:sustain, doneAction:2); var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = VarSaw.ar(basefreq, 0, Line.ar(0,0.5,sustain*20/slide)); var sound2 = VarSaw.ar(basefreq*(detune/100+1), 0, Line.ar(0,0.5,sustain*20/slide)); var sound3 = VarSaw.ar(basefreq*(-1*detune/100+1), 0, Line.ar(0,0.5,sustain*20/slide)); sound = sound - DelayN.ar(sound2,0.2, Line.ar(0,1,5*sustain/slide)/basefreq) + DelayN.ar(sound3,0.2, Line.ar(0,1,20*sustain/slide)/basefreq); Out.ar(out, DirtPan.ar(sound/2, ~dirt.numChannels, pan, env)); }).add ); // impulse noise with a fadein/out ( SynthDef(\superstatic, {|out, sustain=1, pan, freq, accelerate=0, speed=1 | var sound; var env = EnvGen.ar(Env.sine(1, 0.5), timeScale:sustain, doneAction:2); freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); sound = Dust.ar(freq*40) > 0.5; sound = Pulse.ar(freq*sound*4,0.5,0.5); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); // from synthdef.art // fragment: 2018-08-16 // responds to accelerate (for pitch glide) // detune (in Hz, but even small values are quite noticable) // voice (changes harmonics) // rate (impulse trigger rate) ( SynthDef(\supergrind, {|out, pan, freq, sustain, accelerate, detune=0, voice=0, rate=1, speed=1| var env, trig, loop; freq = (freq * DirtFreqScale.kr(speed, accelerate, sustain))/2; env = EnvGen.ar(Env.linen(0.1, 0.8, 0.1), timeScale:sustain, doneAction:2); trig = Impulse.kr(rate * Duty.kr(1, 0, Dseq(0.25 ! 3 ++ [2], inf))); loop = LocalIn.ar; loop = loop + Impulse.ar(SinOsc.ar(1/4, 0, freq/2, (voice+1.0)*freq)); loop = Mix.ar(DelayC.ar(loop + trig, 1, 1/(2*freq+[detune, -1.0*detune])-ControlDur.ir))/2.0; LocalOut.ar(LeakDC.ar(loop).tanh); loop = loop + DelayC.ar(loop, 0.2, SinOsc.ar(1, 0, 1e-3, 0.1)); loop = GVerb.ar(sin(loop + (8*trig)*4)).sin + loop; Out.ar(out, DirtPan.ar(0.3*loop, ~dirt.numChannels, pan, env)); }).add; ); // from synthdef.art // #nightofprimes // responds to accelerate (for pitch glide) // detune (fractional) // voice (some subtle shaping and reverb changing) // rate (impulse trigger rate) ( SynthDef(\superprimes, {|out, pan, freq, sustain, accelerate, rate=1, detune=0, voice=0, speed=1| var env, sound, primes, trig, phase; freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.linen(0.1, 0.6, 0.3), timeScale:sustain, doneAction:2); primes = [2, 3, 5, 7, 11, 13, 17, 19, 23]; trig = Impulse.ar(30.0/primes/sustain * rate); phase = Phasor.kr(trig, 1.0/primes/ControlRate.ir); sound = SinOsc.ar(freq * (1..primes.size)*[1+(detune/12),1-(detune/12)] / 2.0, phase) * LPF.ar(Decay.ar(trig, (primes+3)*sustain/10), voice.linexp(0,2,30,18000)); sound = GVerb.ar(sound.softclip, 10*voice.linexp(0,5,1,0.01), 10).tanh; sound = SplayAz.ar(primes.size, sound.flat, center:LFNoise2.kr(sustain).range(0,primes.size-1)); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); // from synthdef.art // #wavemechanics // responds to accelerate (for pitch glide) // detune (for pitch randomization) // voice (to color/whiten the noise) // resonance (affects reverberation) ( SynthDef(\superwavemechanics, {|out, pan, freq, sustain, accelerate, detune=0, voice=0, resonance=0, speed=1| var env, sound, i, r, d, bwr, sz; freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); env = EnvGen.ar(Env.sine(1.0), timeScale:sustain, doneAction:2); i = TIRand.kr(0, 3, Impulse.kr(sustain/8).dup(8)); r = [3,5,8,9]/8; detune = min(detune, 1.5); d = Rand(1.6*i - detune, 1.7*i + detune).round(0.25); sound = Resonz.ar(WhiteNoise.ar(0.5), freq * r * d, 0.01 + voice.linexp(0,1,1e-3,1)); sound = HPF.ar(Limiter.ar(55 * GVerb.ar(sound, resonance.linexp(0,1,99,0.1),10) ), 30).sanitize; Out.ar(out, DirtPan.ar(sound.flat, ~dirt.numChannels, pan, env)); }).add; ); // feedback PWM // can use "accelerate" "voice" and "detune" parameters // try `d1 $ s "supertron" # octave 3 # accelerate "0.2"` ( SynthDef(\supertron, {|out, pan, freq, sustain, voice, detune, accelerate, speed=1| var sound, aenv, s1, s2; aenv = EnvGen.ar(Env.linen(0.05, 0.85, 0.1, 1, 'lin'), timeScale:sustain, doneAction:2); freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); sound = LocalIn.ar(1); sound = Mix.ar( Pulse.ar(freq+[1+detune,-1-detune], RLPF.ar(sound, freq/6.1, 1.5).range(0,1-(voice/1.5))) ); sound = LeakDC.ar(sound); LocalOut.ar(sound); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, aenv)) }).add; ); // Vaguely Reese-like synth // can use "accelerate" "voice" and "detune" parameters ( SynthDef(\superreese, {|out, pan, freq, sustain, accelerate, detune=0, voice=0, speed=1| var sound; var env = EnvGen.ar(Env.linen(0.05, 0.8, 0.15), timeScale:sustain, doneAction:2); var q1 = voice.linlin(0,2, 3.0, 0.5); var q2 = voice.linlin(0,2, 2.0, 7.0); freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); sound = Splay.ar( VarSaw.ar(freq*[-1*detune/100+0.99,detune/100+1.01], [0.7,0.5], [0.01,0.02]), 0.2, 1, levelComp:false ); sound = RLPF.ar(sound, freq*10, 1.0/q1); sound = sound.clip2(1.0/5.0)* 5.0; sound = 0.35*RLPF.ar(sound, freq*20, 1.0/q2); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); // 6-op FM synth (DX7-like) // // Works a bit different from the original DX7. Instead of algorithms, you set the amount // of modulation every operator receives from other operators and itself (feedback), virtually // providing an endless number of possible combinations (algorithms). // // Responds to // voice (preset number: [0] is user-defined; [1-5] are randomly generated presets). // lfofreq (overall pitch modulation frequency) // lfodepth (overall pitch modulation amplitude) // // Each operator responds to // amp (operator volume - becomes carrier) // ratio (frequency ratio) // detune (in Hz) // eglevel[1-4] (4 envelope generator levels) // egrate[1-4] (4 envelope generator rates) // // The syntax for operator arguments is [modulatorIndex | egIndex] // // For example: // amp1 1 (op1 as carrier with full volume) // ratio2 2.3 (op2 frequency ratio) // mod11 0.5 (op1 feedback) // mod12 0.78 (op1 modulation amount by op2) // detune1 0.2 (op1 detune) // eglevel12 0.1 (op1 EG level2) // egrate11 0.01 (op1 EG rate1) -- WARNING: higher values go FASTER! ( SynthDef(\superfm, { var sustain = \sustain.kr(1); var lfofreq = \lfofreq.kr(1); var lfodepth = \lfodepth.kr(0); var freq = \freq.kr(440); var tremolo = 1 + (LFTri.kr(lfofreq) * lfodepth); var out = \out.kr(0); var pan = \pan.kr(0); var voice = \voice.kr(0); // overall envelope var env = EnvGen.ar(Env.linen(0.01, 0.98, 0.01, 1, -3), timeScale:sustain, doneAction:2); // operator output levels var amps = Array.fill(6, { |i| (\amp++(i+1)).asSymbol.kr(1)}); // operator frequency ratios var ratios = Array.fill(6, {|i| (\ratio++(i+1)).asSymbol.kr(1)}); // operator frequency detuners var detunes = Array.fill(6, {|i| (\detune++(i+1)).asSymbol.kr(rand2(0.1))}); // feedback -- for presets only var feedback = \feedback.kr(0.0); // operator envelopes var eglevels = Array.fill(6, {|i| Array.fill(4, { |n| (\eglevel++(i+1)++(n+1)).asSymbol.kr(1) }) }); var egrates = Array.fill(6, {|i| [ // Supercollider envelopes use seconds for the durations of segments. // So higher values mean transitions are slower. // DX7s envelopes use rates, which is the inverse of time, 1/time. // Higher values in DX7 mean transitions are faster. max(0.1 / ((\egrate++(i+1)++1).asSymbol).ir(10), 0.001), max(0.1 / ((\egrate++(i+1)++2).asSymbol).ir(0.3), 0.001), max(0.1 / ((\egrate++(i+1)++3).asSymbol).ir(0.1), 0.001), max(0.1 / ((\egrate++(i+1)++4).asSymbol).ir(0.1), 0.001), ]}); // modulation matrix var mods = Array.fill2D(6, 6, { |r, c| (\mod++(r+1)++(c+1)).asSymbol.kr(0) * if(r == c, feedback, 1) }); var presets = SelectX.kr(voice, [ [ // user-defined ratios, detunes, amps, eglevels, egrates, mods, ], ] ++ // randomly generated presets Array.fill(5, { [ // ratios Array.fill(6, { [0.25, 0.5, 1, 2, 3, 4, 5, 6, 7, 11.rand + 1, 13.rand + 1, 15.rand + 1].wchoose( [1, 2, 8, 4, 3, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.25].normalizeSum) }), // detunes Array.fill(6, { rand2(7) }), // amps Array.fill(6, { 1.0.rand * 0.5.coin.asInteger }), // EG levels Array.fill2D(6, 4, {1.0.rand}), // EG rates Array.fill2D(6, 4, {1.0.rand}), // mods Array.fill2D(6, 6, {|r,c| 1.0.rand * 0.25.coin.asInteger * if(r == c, feedback, 1)}), ]}) ); var envs = Array.fill(6, { |i| EnvGen.kr( Env.new( // EG levels [0]++Array.fill(4, { |n| presets[3][i][n] }), // EG rates Array.fill(4, { |n| presets[4][i][n] }) ), timeScale:sustain, ); }); var ctls = Array.fill(6, { |i| [freq * tremolo * presets[0][i] + presets[1][i], 0, envs[i]] }); var sound = FM7.ar(ctls, presets[5]) * amps; sound = Mix.ar(sound) * (-15.dbamp); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); ( // DrumSynths SC Example - SOS Drums by Renick Bell, renick@gmail.com // recipes from Gordon Reid in his Sound on Sound articles // SOSkick — http:www.soundonsound.com/sos/jan02/articles/synthsecrets0102.asp // increase pitch1 and voice for interesting electronic percussion // Adapted to SuperDirt by Aleksandr Yakunichev, hi@ya.codes // // midinote – controls the root note of the kick // pitch1 - controls modulation frequency in Hz (min: 0, max: SampleRate.ir / 2) // voice - controls modulation input phase in radians (min: 0, max: your sanity) // pitch2 - controls WhiteNoise amplitude (min: 0, max: 1) // speed - controls WhiteNoise sweep (min: 0, max: 1) SynthDef(\soskick, { |out, pan, freq = 65, pitch1 = 0, speed = 0.3, voice = 1, sustain = 1, pitch2 = 0.00| var beater, source, env; env = Env.perc(0.005, sustain).ar(Done.freeSelf); source = Line.ar(freq * 2, freq, 0.02); source = PMOsc.ar(source, pitch1, voice); source = LPF.ar(source, 1000); beater = WhiteNoise.ar(pitch2.clip); beater = HPF.ar(beater, 500); beater = LPF.ar(beater, XLine.ar(6000, 500, speed.clip * 0.1)); beater = beater * Env.perc.ar; Out.ar(out, DirtPan.ar((source + beater) * 3.dbamp, ~dirt.numChannels, pan, env)); }, metadata: ( credit: "Renick Bell", category: \drums, tags: [\pitched, \bass, \sos] )).add; ); ( // Retrieved from http://sccode.org/1-5aD // DrumSynths SC Example - SOS Drums by Renick Bell, renick@gmail.com // Recipes from Gordon Reid in his Sound on Sound articles // SOShats — http:www.soundonsound.com/sos/Jun02/articles/synthsecrets0602.asp // Modified by Bruno Ruviaro and Josh Mitchell 8/19 // Adapted to SuperDirt by Aleksandr Yakunichev, hi@ya.codes // // resonance – bandpass filter resonance value (min: 0, max: 1) // pitch1 - oscillator modulation in radians (min: 0, max: SampleRate.ir / 2) SynthDef(\soshats, { arg out = 0, pan = 0, freq = 220, pitch1 = 238.5, resonance = 1, sustain = 0.5; var source, envelope, bpf, hpf; source = Mix(PMOsc.ar(Pulse.ar(freq), freq * [1.34, 2.405, 3.09, 1.309], pitch1 * [1, 0.22, 0.014, 0.0038])); bpf = BPF.ar( source, XLine.kr(15000, 9000, sustain), Clip.ir(resonance, 0, 1), Env.perc(0.005, sustain, curve: -4).ar ); hpf = HPF.ar( source, XLine.kr(9000, 12000, sustain), Env.perc(0.005, sustain, curve: -4).ar ); envelope = Env.perc(0.005, sustain).ar(Done.freeSelf); Out.ar(out, DirtPan.ar((bpf + hpf) * (-5).dbamp, ~dirt.numChannels, pan, envelope)); }, metadata: ( credit: "Renick Bell", category: \drums, tags: [\pitched, \hihats, \sos] )).add; ); ( // Retrieved from http:sccode.org/1-5aD // DrumSynths SC Example - SOS Drums by Renick Bell, renick_at_gmail.com // recipes from Gordon Reid in his Sound on Sound articles // SOStom — http:www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp // Modified by Bruno Ruviaro and Josh Mitchell 8/19. // Adapted to SuperDirt by Aleksandr Yakunichev, hi@ya.codes // // voice - controls modulation input phase in radians (min: 0, max: your sanity) SynthDef(\sostoms, { arg out, pan, sustain = 0.5, freq = 261.626, voice = 0.5; var envelope, source; source = PMOsc.ar(Saw.ar(freq * 0.9), freq * 0.85, voice, mul: 6.dbamp); source = source + SinOsc.ar([freq, freq * 0.8]); source = Mix.ar(source); source = LeakDC.ar(source + Crackle.ar(2)) * (-3).dbamp; envelope = Env.perc(0.005, sustain, (-4).dbamp, -6).ar(Done.freeSelf); Out.ar(out, DirtPan.ar(source, ~dirt.numChannels, pan, envelope)); }, metadata: ( credit: "Renick Bell", category: \drums, tags: [\pitched, \tom, \sos] )).add; ); ( // Retrieved from http:sccode.org/1-5aD // DrumSynths SC Example — SOS Drums by Renick Bell, renick_at_gmail.com // recipes from Gordon Reid in his Sound on Sound articles // SOSsnare — http:www.soundonsound.com/sos/Mar02/articles/synthsecrets0302.asp // Latch.ar(WhiteNoise.ar(0.1), Impulse.ar(nyquist * 2)) is added aliasing for effect // Modified by Bruno Ruviaro and Josh Mitchell 8/19. // Adapted to SuperDirt by Aleksandr Yakunichev, hi@ya.codes // // voice - controls modulation input phase in radians (min: 0, max: your sanity) // semitone - modulation frequency in semitones of fundamental // pitch1 - resonance filter frequency (Hz) // resonance - resonance of bandpass and resonz filters (min: 0, max: 1) SynthDef(\sossnare, { arg out, pan, freq = 405, voice = 0.385, semitone = 0.452, pitch1 = 2000, resonance = 0.1, sustain = 0.5; var source, noise, envelope; source = PMOsc.ar(Saw.ar(freq * 0.85), freq * semitone, voice); noise = Latch.ar(WhiteNoise.ar(0.1), Impulse.ar(1700 * 2)); noise = BRF.ar(noise, 4 * pitch1, resonance, 0.5); noise = BRF.ar(noise, 2.5 * pitch1, resonance, 0.5); noise = BRF.ar(noise, 1.8 * pitch1, resonance, 0.5); noise = BRF.ar(noise, pitch1, resonance, Env.perc(0.005, sustain, -4).ar); noise = Resonz.ar(noise, pitch1, 1, 40); envelope = Env.perc(0.005, sustain, 0.5, -4).ar(Done.freeSelf); Out.ar(out, DirtPan.ar((source + noise) * 4.dbamp, ~dirt.numChannels, pan, envelope)); }, metadata: ( credit: "Renick Bell", category: \drums, tags: [\pitched, \snare, \sos] )).add; );