From b0dce42be701f72a93812703409792205da7a7e8 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 18 Aug 2024 17:12:39 -0400 Subject: [PATCH 01/34] fixed amp --- synths/core-synths.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 3f37799a..0ef3169c 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -178,7 +178,7 @@ live coding them requires that you have your SuperDirt instance in an environmen var signal = In.ar(in, numChannels); // doneAction: 14: free surrounding group and all nodes var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain, fadeTime], \sin), doneAction: 14); - amp = amp * pow(gain.min(2) + overgain, 4); + amp = amp * (gain + overgain); signal = signal * env * amp * DirtGateCutGroup.ar(fadeTime, doneAction: 14); // this takes the signal and offsets it so it matches precisely onto the sample // as scheduled within one block (a synth is always started on the block bondary) From fc4c24f77093c39a094256eac0cb40e5a57aa83f Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 18 Aug 2024 18:52:34 -0400 Subject: [PATCH 02/34] clip --- classes/DirtEvent.sc | 5 +++-- hacks/external-interfacing.scd | 2 +- hacks/jitlib-hacks.scd | 10 +++++----- hacks/sclang-dirt.scd | 2 +- scripts/internal-routing-test.scd | 2 +- scripts/tidal-midi.scd | 2 +- used-parameters.scd | 2 +- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 03f07524..38258a77 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -104,8 +104,8 @@ DirtEvent { sustain = ~sustain.value; sustain = sustain ?? { delta = ~delta.value; - if(~legato.notNil) { - delta * ~legato.value + if(~clip.notNil) { + (delta / ~cps) * ~clip.value } { unitDuration = unitDuration ? delta; loop !? { unitDuration = unitDuration * loop.abs }; @@ -120,6 +120,7 @@ DirtEvent { ~fadeInTime = if(~begin != 0) { ~fadeTime } { 0.0 }; if (~timescale.notNil) {sustain = sustain * ~timescale }; ~sustain = sustain - (~fadeTime + ~fadeInTime); + // ~sustain = (~delta.value / ~cps) * ~clip.value ? 1; ~speed = speed; ~endSpeed = endSpeed; diff --git a/hacks/external-interfacing.scd b/hacks/external-interfacing.scd index 5a2e0c93..3714118f 100644 --- a/hacks/external-interfacing.scd +++ b/hacks/external-interfacing.scd @@ -15,7 +15,7 @@ SynthDef(\gendy, { |out, sustain = 1, freq = 440, pan, fratio = 0| ); // play it in tidal: -// d1 $ s "gendy" # legato "1.2" +// d1 $ s "gendy" # clip "1.2" ~dirt.set(\fratio, Ndef(\ctrl1)); diff --git a/hacks/jitlib-hacks.scd b/hacks/jitlib-hacks.scd index db27357e..b2b919ed 100644 --- a/hacks/jitlib-hacks.scd +++ b/hacks/jitlib-hacks.scd @@ -74,7 +74,7 @@ Pdef(\x, \s, Pn(Pshuf([\bd, \hh, \cp, \imp], 5)), \begin, Pn(Pseries(0, 0.002, 20)), \dur, 0.1, - \legato, Pwhite(0.01, 0.4) + \clip, Pwhite(0.01, 0.4) ) ).play; ) @@ -88,7 +88,7 @@ Pdef(\x, \begin, Pn(Pseries(0, 0.002, 20)), \bandf, Pfunc { exprand(130, 10000) }, \dur, 0.1, - \legato, Pwhite(0.01, 0.4) + \clip, Pwhite(0.01, 0.4) ) ).play; ) @@ -104,7 +104,7 @@ Pdef(\x, \instrument, Pn(Pshuf([\bd, \hh, \cp, \imp], 5)), \begin, Pn(Pseries(0, 0.002, 20)), \dur, 0.1, - \legato, Pwhite(0.01, 0.4) + \clip, Pwhite(0.01, 0.4) ) ).play; ) @@ -118,7 +118,7 @@ Pdef(\x, \dur, 0.11, \room, Pseq([0, 0, 0.5, 0, 0], inf), \pan, Pseq([0, 1], inf), - \legato, Pwhite(0.01, 1.4) + Pwrand([0, 16], [0.9, 0.1], inf) + \clip, Pwhite(0.01, 1.4) + Pwrand([0, 16], [0.9, 0.1], inf) ) ).play; ) @@ -132,7 +132,7 @@ Pdef(\x, \dur, Prand((3..5).collect{ |x| Pn(2 ** neg(x), x) }, inf), \room, Pseq([0, 0, 0.5, 0, 0], inf), \pan, Pseq([0, 1], inf), - \legato, Pwhite(0.01, 1.4) + Pwrand([0, 16], [0.9, 0.1], inf) + \clip, Pwhite(0.01, 1.4) + Pwrand([0, 16], [0.9, 0.1], inf) ) ).play; ) diff --git a/hacks/sclang-dirt.scd b/hacks/sclang-dirt.scd index af9fde5f..8e04da82 100644 --- a/hacks/sclang-dirt.scd +++ b/hacks/sclang-dirt.scd @@ -39,7 +39,7 @@ Pdef(\x, \n, Pwhite(0, 20, inf), \speed, Pbrown(1, 1.2, 0.01), \amp, Pwhite().linexp(0, 1, 0.001, 0.3), - \legato, 2, + \clip, 2, \dur, 1 / 32 * Pshuf([1, 1/2, 1, 2, 2, 1/2], inf), \room, Pwrand([0, 0.8], [0.9, 0.1], inf), ) diff --git a/scripts/internal-routing-test.scd b/scripts/internal-routing-test.scd index 53c6de98..eefb2c97 100644 --- a/scripts/internal-routing-test.scd +++ b/scripts/internal-routing-test.scd @@ -43,7 +43,7 @@ Pdef(\x, \modfreq, Pseq([2, Prand([3, 7], 1), 0.3, 0.4], inf), \rq, Pwhite().linexp(0, 1, 0.05, 0.3), \dur, 1, //1/Pseq([1, 3, 2, 1], inf), - \legato, 2, + \clip, 2, \pan, 0, //Pseq([0, 1], inf) ) ]) diff --git a/scripts/tidal-midi.scd b/scripts/tidal-midi.scd index 3edc3890..8a7e807e 100644 --- a/scripts/tidal-midi.scd +++ b/scripts/tidal-midi.scd @@ -45,7 +45,7 @@ d1 $ ccn "28*16" # ccv 127 # s "midi" # midichan 9 // note: parameter names may change in the future! // In supercollider terms, the following midicmds and their parameters are supported -// (the usual note/freq and legato/sustain parameters are taken into account) +// (the usual note/freq and clip/sustain parameters are taken into account) polyTouch: midichan, midinote, polyTouch program: midichan, progNum diff --git a/used-parameters.scd b/used-parameters.scd index 19be9417..225d2b5c 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -30,7 +30,7 @@ cps unit loop delta -legato +clip sustain amp gain From e58583e3e24e34b6280c80175963d0e0040fe856 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 19 Aug 2024 23:14:16 -0400 Subject: [PATCH 03/34] adjusted envelope behavior --- classes/DirtEvent.sc | 4 ++++ classes/DirtOrbit.sc | 8 ++++---- library/strudel-synths.scd | 21 +++++++++++++++++++++ synths/core-modules.scd | 4 +++- synths/core-synths.scd | 27 +++++++++++++++++++++++++-- synths/default-synths.scd | 16 ++++++++++++++++ synths/try-load-extra-synths.scd | 1 + used-parameters.scd | 1 + 8 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 library/strudel-synths.scd diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 38258a77..c44d20d5 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -67,6 +67,7 @@ DirtEvent { var accelerate = ~accelerate.value; var avgSpeed, endSpeed; var useUnit; + var release = ~release.value ? 0.0; ~freq = ~freq.value; unitDuration = ~unitDuration.value; @@ -102,6 +103,7 @@ DirtEvent { }; sustain = ~sustain.value; + sustain = sustain ?? { delta = ~delta.value; if(~clip.notNil) { @@ -111,6 +113,8 @@ DirtEvent { loop !? { unitDuration = unitDuration * loop.abs }; } }; + sustain = sustain + release; + // end samples if sustain exceeds buffer duration // for every buffer, unitDuration is (and should be) defined. diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index b69479bf..60dd4979 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -159,7 +159,7 @@ DirtOrbit { globalEffectBus.free; } - +// if(~note.isNil) { if (~n.isNil) { 57 } { ~n } } { ~note } makeDefaultParentEvent { defaultParentEvent = Event.make { @@ -174,9 +174,9 @@ DirtOrbit { ~cut = 0.0; ~unit = \r; ~n = \none; // sample number or note - ~octave = 5; - ~midinote = #{ ~note ? ~n + (~octave * 12) }; - ~freq = #{ ~midinote.value.midicps }; + ~octave = 0; + ~midinote = #{ (~note ? ~n) + (~octave * 12) }; + ~freq = #{ ~midinote.value.midicps }; ~dur = 1.0; ~delta = #{ ~dur.value }; diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd new file mode 100644 index 00000000..7ceeb585 --- /dev/null +++ b/library/strudel-synths.scd @@ -0,0 +1,21 @@ + +( + SynthDef(\sawtooth, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, 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); + // // EnvGen.ar(Env.adsr()) + + // EnvGen.kr(Env( + + // )) + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + + + // 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; + var sound = Saw.ar(basefreq, 1.0); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add +); \ No newline at end of file diff --git a/synths/core-modules.scd b/synths/core-modules.scd index add1139a..e1944021 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -174,12 +174,14 @@ this may be refacored later. dirtEvent.sendSynth('dirt_envelope' ++ ~numChannels, [ attack: ~attack, + decay: ~decay, hold: ~hold, + holdtime: ~sustain, release: ~release, curve: ~curve, out: ~out ]) -}, { ~attack.notNil or: { ~release.notNil }}); +}, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); ~dirt.addModule('grenvelo', { |dirtEvent| diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 0ef3169c..c0546fa6 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -270,9 +270,32 @@ live coding them requires that you have your SuperDirt instance in an environmen ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; - SynthDef("dirt_envelope" ++ numChannels, { |out, attack = 0, hold = 0, release = inf, curve = -3 | + SynthDef("dirt_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve = -3 | + var envmin = 0.0; + var envmax = 1.0; var signal = In.ar(out, numChannels); - signal = signal * EnvGen.ar(Env.linen(attack, hold, release, 1, curve: curve)); + + if (hold.isNil) { + if (decay.isNil) { + hold = envmax; + } { + hold = envmin; + }; + }; + + attack = attack ? envmin; + decay = decay ? envmin; + release = release ? envmin; + holdtime = holdtime - attack - decay; + + signal = signal * EnvGen.ar( + Env.new( + levels: [0, 1, hold, 0], + times: [attack, decay, holdtime, release], + curve: curve + ), + // doneAction: 2 + ); ReplaceOut.ar(out, signal); }, [\ir, \ir, \ir, \ir, \ir]).add; diff --git a/synths/default-synths.scd b/synths/default-synths.scd index ba96d122..ecfaaee4 100644 --- a/synths/default-synths.scd +++ b/synths/default-synths.scd @@ -39,6 +39,22 @@ SynthDef(\psin, { |out, sustain = 1, freq = 440, speed = 1, begin=0, end=1, pan, phase = Line.ar(begin, end, sustain); rate = speed + Sweep.kr(1, accelerate); sound = SinOsc.ar(freq, SinOsc.ar(modfreq * (1..5), 0, 1 - phase * 10 * env / (1..5), 0.5pi)).sum; + + Out.ar(out, + DirtPan.ar(sound, ~dirt.numChannels, pan, env) + ) +}).add +); + +( +SynthDef(\psin, { |out, sustain = 1, freq = 440, speed = 1, begin=0, end=1, pan, accelerate, offset, modfreq = 40| + 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, SinOsc.ar(modfreq * (1..5), 0, 1 - phase * 10 * env / (1..5), 0.5pi)).sum; + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env) ) diff --git a/synths/try-load-extra-synths.scd b/synths/try-load-extra-synths.scd index f80743de..7fb18b2d 100644 --- a/synths/try-load-extra-synths.scd +++ b/synths/try-load-extra-synths.scd @@ -2,5 +2,6 @@ if(\MembraneHexagon.asClass.isNil) { "Dirt could not load some synths from default-synths.scd, because sc3plugins are necessary and missing.".warn } { loadRelative("../library/default-synths-extra.scd"); + loadRelative("../library/strudel-synths.scd"); loadRelative("../library/default-effects-extra.scd"); }; diff --git a/used-parameters.scd b/used-parameters.scd index 225d2b5c..3a13c802 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -82,6 +82,7 @@ crush coarse cutoff attack +decay release hold tremolorate From 789eaceff1bb21cd55a710086ab888ca97fb7b8e Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 20 Aug 2024 01:03:19 -0400 Subject: [PATCH 04/34] lp envelope --- classes/SuperDirtUGens.sc | 23 ++++++++++++++++++++ synths/core-modules.scd | 6 ++++++ synths/core-synths.scd | 44 ++++++++++++++------------------------- used-parameters.scd | 5 +++++ 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/classes/SuperDirtUGens.sc b/classes/SuperDirtUGens.sc index a18d1e9b..9c7f7dd9 100644 --- a/classes/SuperDirtUGens.sc +++ b/classes/SuperDirtUGens.sc @@ -196,4 +196,27 @@ DirtPause { } +DirtEnvelope { + *adsr { |attack, decay, holdtime = 0, release, hold, envmin = 0, envmax = 1, curve = -3 | + if (hold.isNil) { + if (decay.isNil) { + hold = envmax; + } { + hold = envmin; + }; + }; + + attack = attack ? envmin; + decay = decay ? envmin; + release = release ? envmin; + holdtime = holdtime - attack - decay; + + ^Env.new( + levels: [envmin, envmax, hold, envmin], + times: [attack, decay, holdtime, release], + curve: curve + ) + } +} + diff --git a/synths/core-modules.scd b/synths/core-modules.scd index e1944021..74289254 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -153,6 +153,12 @@ this may be refacored later. [ cutoff: ~cutoff, resonance: ~resonance, + lpenv: ~lpenv, + lpattack: ~lpattack, + lpdecay: ~lpdecay, + lpsustain: ~lpsustain, + lprelease: ~lprelease, + lpholdtime: ~sustain, out: ~out ]) diff --git a/synths/core-synths.scd b/synths/core-synths.scd index c0546fa6..a1053ad8 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -11,13 +11,13 @@ Their name and parameter names shouldn't be changed. Parameter names can be adde live coding them requires that you have your SuperDirt instance in an environment variable called ~dirt. */ + ( { var numChannels = ~dirt.numChannels; - // write variants for different sample buffer sizes (1..SuperDirt.maxSampleNumChannels).do { |sampleNumChannels| @@ -264,38 +264,26 @@ live coding them requires that you have your SuperDirt instance in an environmen ReplaceOut.ar(out, signal * amp) }, [\ir, \kr]).add; - SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0| + SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, lpattack, lpsustain, lpdecay, lpenv = 400, lprelease, lpholdtime | var signal = In.ar(out, numChannels); - signal = RLPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), resonance.linexp(0, 1, 1, 0.001)); + var envmax = SampleRate.ir / 2; + var envmin = 20; + + cutoff = cutoff + EnvGen.ar( + DirtEnvelope.adsr(lpattack, lpdecay, lpholdtime, lprelease, lpsustain, 0, lpenv, -4); + ); + + cutoff = cutoff.abs.clip(envmin, envmax); + + signal = RLPF.ar(signal, cutoff, resonance.linexp(0, 1, 1, 0.001)); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; SynthDef("dirt_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve = -3 | - var envmin = 0.0; - var envmax = 1.0; - var signal = In.ar(out, numChannels); - - if (hold.isNil) { - if (decay.isNil) { - hold = envmax; - } { - hold = envmin; - }; - }; - - attack = attack ? envmin; - decay = decay ? envmin; - release = release ? envmin; - holdtime = holdtime - attack - decay; - - signal = signal * EnvGen.ar( - Env.new( - levels: [0, 1, hold, 0], - times: [attack, decay, holdtime, release], - curve: curve - ), - // doneAction: 2 - ); + var signal = In.ar(out, numChannels); + signal = signal * EnvGen.ar( + DirtEnvelope.adsr(attack, decay, holdtime, release, hold, 0, 1, curve); + ); ReplaceOut.ar(out, signal); }, [\ir, \ir, \ir, \ir, \ir]).add; diff --git a/used-parameters.scd b/used-parameters.scd index 3a13c802..8fe5d144 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -81,6 +81,11 @@ bandq crush coarse cutoff +lpattack +lpdecay +lpsustain +lprelease +lpenv attack decay release From 42b282fdd5336dd7e52ac46548be90f0e57b3d02 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 23 Aug 2024 01:19:34 -0400 Subject: [PATCH 05/34] feat: filter envelope --- classes/DirtEvent.sc | 6 ++--- classes/SuperDirtUGens.sc | 44 +++++++++++++++++++++++++---------- synths/core-modules.scd | 16 ++++++------- synths/core-synths.scd | 49 ++++++++++++++++++++++++++++----------- 4 files changed, 78 insertions(+), 37 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index c44d20d5..d0569595 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -113,18 +113,17 @@ DirtEvent { loop !? { unitDuration = unitDuration * loop.abs }; } }; - sustain = sustain + release; + // sustain = sustain + release; // end samples if sustain exceeds buffer duration // for every buffer, unitDuration is (and should be) defined. if(useUnit) { sustain = min(unitDuration, sustain) }; - + ~fadeTime = min(~fadeTime.value, sustain * 0.19098); ~fadeInTime = if(~begin != 0) { ~fadeTime } { 0.0 }; if (~timescale.notNil) {sustain = sustain * ~timescale }; ~sustain = sustain - (~fadeTime + ~fadeInTime); - // ~sustain = (~delta.value / ~cps) * ~clip.value ? 1; ~speed = speed; ~endSpeed = endSpeed; @@ -170,6 +169,7 @@ DirtEvent { overgain: ~overgain, sample: ~hash, // required for the cutgroup mechanism cut: ~cut.abs, + release: ~release, sustain: ~sustain, // after sustain, free all synths and group fadeInTime: ~fadeInTime, // fade in fadeTime: ~fadeTime // fade out diff --git a/classes/SuperDirtUGens.sc b/classes/SuperDirtUGens.sc index 9c7f7dd9..5726be27 100644 --- a/classes/SuperDirtUGens.sc +++ b/classes/SuperDirtUGens.sc @@ -197,25 +197,45 @@ DirtPause { } DirtEnvelope { - *adsr { |attack, decay, holdtime = 0, release, hold, envmin = 0, envmax = 1, curve = -3 | + *adsr { + |attack, decay, holdtime, hold, release, envmin = 0, envmax = 1, curve = -4| if (hold.isNil) { if (decay.isNil) { hold = envmax; } { hold = envmin; }; + } { + hold = envmin + ((envmax - envmin) * hold).clip(envmin, envmax); }; - - attack = attack ? envmin; - decay = decay ? envmin; - release = release ? envmin; - holdtime = holdtime - attack - decay; - - ^Env.new( - levels: [envmin, envmax, hold, envmin], - times: [attack, decay, holdtime, release], - curve: curve - ) + + + + // decay = decay + attack; + // release = holdtime + release; + + // ^Env.pairs( + // [[0, envmin], + // [attack, envmax], + // [decay, hold], + // [holdtime, hold], + // [release, envmin]], + // curve: curve + // ) + ^Env.adsr( + attackTime: attack, + decayTime:decay, + sustainLevel: hold, + releaseTime: release, + peakLevel: envmax, + curve: curve, + bias: envmin + ) + // ^Env.new( + // levels: [envmin, envmax, hold, envmin], + // times: [attack, decay, holdtime], + // curve: curve + // ) } } diff --git a/synths/core-modules.scd b/synths/core-modules.scd index 74289254..648c0b09 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -153,12 +153,12 @@ this may be refacored later. [ cutoff: ~cutoff, resonance: ~resonance, - lpenv: ~lpenv, - lpattack: ~lpattack, - lpdecay: ~lpdecay, - lpsustain: ~lpsustain, - lprelease: ~lprelease, - lpholdtime: ~sustain, + envamt: ~lpenv, + attack: {~lpattack.value ? ~attack.value}, + decay: {~lpdecay.value ? ~decay.value}, + hold: { ~lpsustain.value ? ~hold.value ? ~lpdecay.isNil}, + release: {~lprelease.value ? ~release.value}, + holdtime: ~sustain, out: ~out ]) @@ -181,10 +181,10 @@ this may be refacored later. [ attack: ~attack, decay: ~decay, - hold: ~hold, + hold: { ~hold.value ? ~decay.isNil }, holdtime: ~sustain, release: ~release, - curve: ~curve, + curve: {~curve.value ? -2}, out: ~out ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); diff --git a/synths/core-synths.scd b/synths/core-synths.scd index a1053ad8..b68076d2 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -174,10 +174,10 @@ live coding them requires that you have your SuperDirt instance in an environmen // the monitor does the mixing and zeroing of the busses for each sample grain // so that they can all play in one bus - SynthDef("dirt_gate" ++ numChannels, { |out, in, sustain = 1, fadeInTime = 0.001, fadeTime = 0.001, amp = 1, gain = 1, overgain = 0| + SynthDef("dirt_gate" ++ numChannels, { |out, in, sustain = 1, release = 0, fadeInTime = 0.001, fadeTime = 0.001, amp = 1, gain = 1, overgain = 0| var signal = In.ar(in, numChannels); // doneAction: 14: free surrounding group and all nodes - var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain, fadeTime], \sin), doneAction: 14); + var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain + release, fadeTime], \sin), doneAction: 14); amp = amp * (gain + overgain); signal = signal * env * amp * DirtGateCutGroup.ar(fadeTime, doneAction: 14); // this takes the signal and offsets it so it matches precisely onto the sample @@ -196,6 +196,7 @@ live coding them requires that you have your SuperDirt instance in an environmen SynthDef("dirt_out" ++ numChannels, { |out, to, sustain = 1, fadeInTime = 0.001, fadeTime = 0.001, through = 0, amp = 1| var signal = In.ar(out, numChannels); var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain, fadeTime], \sin)); + Out.ar(to, signal * env * amp); ReplaceOut.ar(out, signal * through); }, [\ir, \ir, \ir, \ir, \ir, \ir, \kr]).add; // amp can be modulated @@ -264,26 +265,46 @@ live coding them requires that you have your SuperDirt instance in an environmen ReplaceOut.ar(out, signal * amp) }, [\ir, \kr]).add; - SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, lpattack, lpsustain, lpdecay, lpenv = 400, lprelease, lpholdtime | + SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | var signal = In.ar(out, numChannels); - var envmax = SampleRate.ir / 2; - var envmin = 20; - - cutoff = cutoff + EnvGen.ar( - DirtEnvelope.adsr(lpattack, lpdecay, lpholdtime, lprelease, lpsustain, 0, lpenv, -4); + var cutmax = SampleRate.ir / 2; + var cutmin = 20; + var offset = envamt.abs * anchor; + + var envmin = clip(2 ** (offset * -1) * cutoff, cutmin, cutmax); + var envmax = clip(2 ** (envamt.abs - offset) * cutoff, cutmin, cutmax); + + cutoff = EnvGen.ar( + Env.adsr( + attackTime: attack, + decayTime: decay, + releaseTime: release, + sustainLevel: hold, + peakLevel: envmax - envmin, + bias: envmin, + curve: -4 + ), + gate: Trig.ar(1, holdtime) ); - cutoff = cutoff.abs.clip(envmin, envmax); - signal = RLPF.ar(signal, cutoff, resonance.linexp(0, 1, 1, 0.001)); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; - SynthDef("dirt_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve = -3 | - var signal = In.ar(out, numChannels); - signal = signal * EnvGen.ar( - DirtEnvelope.adsr(attack, decay, holdtime, release, hold, 0, 1, curve); + SynthDef("dirt_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve | + var signal = In.ar(out, numChannels); + var volenv = EnvGen.ar( + Env.adsr( + attackTime: attack, + decayTime: decay, + releaseTime: release, + sustainLevel: hold, + peakLevel: 1, + curve: curve + ), + gate: Trig.ar(1, holdtime) ); + signal = signal * volenv; ReplaceOut.ar(out, signal); }, [\ir, \ir, \ir, \ir, \ir]).add; From d0c7fcb49cdeb9bdcffe3cba41de3a2e37c62687 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 25 Aug 2024 01:09:01 -0400 Subject: [PATCH 06/34] working on supersaw --- classes/SuperDirtUGens.sc | 12 +++++++ library/default-synths-extra.scd | 2 +- library/strudel-synths.scd | 59 ++++++++++++++++++++++++-------- 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/classes/SuperDirtUGens.sc b/classes/SuperDirtUGens.sc index 5726be27..766d4573 100644 --- a/classes/SuperDirtUGens.sc +++ b/classes/SuperDirtUGens.sc @@ -196,6 +196,18 @@ DirtPause { } +StrudelUtils { + *lerp {|a, b, n| + var result = n * (b - a) + a; + ^result; + } + *getUnisonDetune { | unison, detune, voiceIndex | + var amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); + ^amount; + } + +} + DirtEnvelope { *adsr { |attack, decay, holdtime, hold, release, envmin = 0, envmax = 1, curve = -4| diff --git a/library/default-synths-extra.scd b/library/default-synths-extra.scd index df139191..52f0bfc6 100644 --- a/library/default-synths-extra.scd +++ b/library/default-synths-extra.scd @@ -187,7 +187,7 @@ // 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, + SynthDef(\supersawold, {|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); diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 7ceeb585..0c3acc5a 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,21 +1,52 @@ + ( + SynthDef(\sawtooth, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, 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); - // // EnvGen.ar(Env.adsr()) + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = SawDPW.ar(freq: basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + + SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = SinOsc.ar(basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; - // EnvGen.kr(Env( + SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = LFTri.ar(basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; - // )) + SynthDef(\supersaw, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq =130.8, speed=1, unison = 5, spread = 0.5, detune = 0.15| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - - - // 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; - var sound = Saw.ar(basefreq, 1.0); + var sound; + var voicedetuneamt; + var voices = unison; + var panspread = spread; + var freqspread = detune; + var gain1 = sqrt(1 - panspread); + var gain2 = sqrt(panspread); + + voices = clip(unison, 0, 100); + panspread = if (voices > 1) { clip(spread,0,1) } {0}; + + panspread = panspread * 0.5 + 0.5; + sound = Mix.arFill(voices, {|n| + voicedetuneamt = squared(StrudelUtils.getUnisonDetune(voices, freqspread, n) / 12); + + + + SawDPW.ar(basefreq * voicedetuneamt) + }); + + + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add -); \ No newline at end of file + }).add; + + +); From 7b768d05ec41cd4afaff3ba8e498af444b2a51e3 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 27 Aug 2024 00:18:29 -0400 Subject: [PATCH 07/34] simplifying supersaw --- classes/DirtEvent.sc | 7 +++ library/default-synths-extra.scd | 10 ++-- library/strudel-synths.scd | 91 ++++++++++++++++---------------- used-parameters.scd | 3 ++ 4 files changed, 61 insertions(+), 50 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index d0569595..7c60e338 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -144,7 +144,14 @@ DirtEvent { sendSynth { |instrument, args| var group = ~synthGroup; args = args ?? { this.getMsgFunc(instrument).valueEnvir }; + args.asControlInput.flop.do { |each| + // instrument.value.postln; + // if (instrument.value == "supersaw") { + // "HI".postln; + // }; + + server.sendMsg(\s_new, instrument, -1, // no id diff --git a/library/default-synths-extra.scd b/library/default-synths-extra.scd index 52f0bfc6..a7ecc443 100644 --- a/library/default-synths-extra.scd +++ b/library/default-synths-extra.scd @@ -194,10 +194,12 @@ 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); + var sound = Mix.arFill(3, {|n| SawDPW.ar(basefreq * ((n-1)*voice/50+1), 0)}); + // 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 diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 0c3acc5a..4bb804b1 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,52 +1,51 @@ ( - - SynthDef(\sawtooth, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound = SawDPW.ar(freq: basefreq); - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; - - SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound = SinOsc.ar(basefreq); - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; - - SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound = LFTri.ar(basefreq); - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; - - SynthDef(\supersaw, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq =130.8, speed=1, unison = 5, spread = 0.5, detune = 0.15| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound; - var voicedetuneamt; - var voices = unison; - var panspread = spread; - var freqspread = detune; - var gain1 = sqrt(1 - panspread); - var gain2 = sqrt(panspread); - - voices = clip(unison, 0, 100); - panspread = if (voices > 1) { clip(spread,0,1) } {0}; - - panspread = panspread * 0.5 + 0.5; - sound = Mix.arFill(voices, {|n| - voicedetuneamt = squared(StrudelUtils.getUnisonDetune(voices, freqspread, n) / 12); - - - - SawDPW.ar(basefreq * voicedetuneamt) - }); - - - - - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; + { + var unison = ~unison.value; + + SynthDef(\sawtooth, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = SawDPW.ar(freq: basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + + SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = SinOsc.ar(basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + + SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = LFTri.ar(basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + + SynthDef(\supersaw, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq =130.8, speed=1, spread = 0.5, detune = 0.15| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound; + var voices = 7; + var panspread = spread; + var freqspread = detune; + var gain1 = sqrt(1 - panspread); + var gain2 = sqrt(panspread); + voices = clip(voices, 0, 100); + + if (voices < 1) { + panspread = 0; + }; + + sound = Splay.arFill(voices, {|i| + SawDPW.ar(basefreq * pow(2, StrudelUtils.getUnisonDetune(voices, freqspread, i) / 12), + iphase: TRand.kr(-1, 1, Impulse.kr(0)) + ) + },spread: panspread, level: 1, center: 0); + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + + }.value ); diff --git a/used-parameters.scd b/used-parameters.scd index 8fe5d144..5185425d 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -90,6 +90,9 @@ attack decay release hold +spread +unison +detune tremolorate tremolodepth phaserrate From c0e7366dd2c2ac0488dce0a3c98ad375958b60bb Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Wed, 28 Aug 2024 22:54:57 -0400 Subject: [PATCH 08/34] supersaw finally --- classes/DirtEvent.sc | 50 +++++++++++++++++++---- classes/DirtOrbit.sc | 6 +++ classes/DirtSoundLibrary.sc | 4 ++ classes/StrudelUtils.sc | 12 ++++++ classes/SuperDirtUGens.sc | 35 +--------------- hacks/jitlib-hacks.scd | 1 + library/strudel-synths.scd | 79 ++++++++++++++++++++++--------------- 7 files changed, 114 insertions(+), 73 deletions(-) create mode 100644 classes/StrudelUtils.sc diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 7c60e338..54608c1c 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -8,10 +8,19 @@ DirtEvent { } play { + + event.parent = orbit.defaultParentEvent; event.use { + + // s and n stand for synth/sample and note/number ~s ?? { this.splitName }; + + // if (~unison.notNil) { + // ~s = ~s ++ ~unison; + // }; + // unless orbit wide diversion returns something, we proceed ~diversion.(this) ?? { if(~s != \) { // backslash stands for do nothing @@ -35,15 +44,27 @@ DirtEvent { } splitName { + var s, n; + + + #s, n = ~sound.asString.split($:); if(~bank.notNil) { s = ~bank ++ s }; ~s = s.asSymbol; + + + + ~n = if(n.notNil) { n.asFloat } { 0.0 }; } mergeSoundEvent { - var soundEvent = orbit.dirt.soundLibrary.getEvent(~s, ~n); + var soundEvent; + + + soundEvent = orbit.dirt.soundLibrary.getEvent(~s, ~n); + if(soundEvent.isNil) { // only call ~notFound if no ~diversion is given that anyhow redirects control if(~diversion.isNil) { ~notFound.value } @@ -146,19 +167,32 @@ DirtEvent { args = args ?? { this.getMsgFunc(instrument).valueEnvir }; args.asControlInput.flop.do { |each| - // instrument.value.postln; - // if (instrument.value == "supersaw") { - // "HI".postln; - // }; - + - server.sendMsg(\s_new, + // if (~unison.notNil) { + // instrument = instrument ++ ~unison; + + // }; + // if (instrument.asString == "supersaw") { + // server.sendMsg(\s_new , + // instrument ++ ~unison.value ? 2, + // -1, // no id + // 1, // add action: addToTail + // group, // send to group + // *each.asOSCArgArray // append all other args + // ) + // } { + server.sendMsg(\s_new, instrument, -1, // no id 1, // add action: addToTail group, // send to group *each.asOSCArgArray // append all other args - ) + ) + // } + + + } } diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 60dd4979..fa09ad6f 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -189,6 +189,12 @@ DirtOrbit { ~amp = 0.4; ~fadeTime = 0.001; + // ~s = {if (~unison.notNil) { + // ~s ++ ~unison; + // } { + // ~s; + // } + // }; // values from the dirt bus diff --git a/classes/DirtSoundLibrary.sc b/classes/DirtSoundLibrary.sc index fa3739d5..a3c4249e 100644 --- a/classes/DirtSoundLibrary.sc +++ b/classes/DirtSoundLibrary.sc @@ -51,6 +51,7 @@ DirtSoundLibrary { } addSynth { |name, event, appendToExisting = false, useSynthDefSustain = false, metaData| + if(bufferEvents[name].notNil) { "a sample buffer with that name already exists: %\nSkipping...".format(name).warn; ^this @@ -107,6 +108,8 @@ DirtSoundLibrary { set { |name, indices ... pairs| var allEvents = this.at(name); + + if(allEvents.isNil) { "set: no events found with this name: %\n".format(name).warn } { @@ -283,6 +286,7 @@ DirtSoundLibrary { var allEvents = this.at(name); var event; + if(allEvents.isNil) { // first look up buffers, then synths diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc new file mode 100644 index 00000000..8702ca9b --- /dev/null +++ b/classes/StrudelUtils.sc @@ -0,0 +1,12 @@ + +StrudelUtils { + *lerp {|a, b, n| + var result = n * (b - a) + a; + ^result; + } + *getUnisonDetune { | unison, detune, voiceIndex | + var amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); + ^amount; + } + +} \ No newline at end of file diff --git a/classes/SuperDirtUGens.sc b/classes/SuperDirtUGens.sc index 766d4573..4fb24751 100644 --- a/classes/SuperDirtUGens.sc +++ b/classes/SuperDirtUGens.sc @@ -183,9 +183,7 @@ DirtGateCutGroup { } } - DirtPause { - *ar { | signal, graceTime = 1, pauseImmediately = 0 | // immediately pause when started PauseSelf.kr(Impulse.kr(0) * pauseImmediately); @@ -193,19 +191,6 @@ DirtPause { signal = signal.abs + Trig1.ar(\resumed.tr(0), graceTime); DetectSilence.ar(signal, time:graceTime, doneAction:1); } - -} - -StrudelUtils { - *lerp {|a, b, n| - var result = n * (b - a) + a; - ^result; - } - *getUnisonDetune { | unison, detune, voiceIndex | - var amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); - ^amount; - } - } DirtEnvelope { @@ -220,20 +205,7 @@ DirtEnvelope { } { hold = envmin + ((envmax - envmin) * hold).clip(envmin, envmax); }; - - - - // decay = decay + attack; - // release = holdtime + release; - - // ^Env.pairs( - // [[0, envmin], - // [attack, envmax], - // [decay, hold], - // [holdtime, hold], - // [release, envmin]], - // curve: curve - // ) + ^Env.adsr( attackTime: attack, decayTime:decay, @@ -243,11 +215,6 @@ DirtEnvelope { curve: curve, bias: envmin ) - // ^Env.new( - // levels: [envmin, envmax, hold, envmin], - // times: [attack, decay, holdtime], - // curve: curve - // ) } } diff --git a/hacks/jitlib-hacks.scd b/hacks/jitlib-hacks.scd index b2b919ed..faff890a 100644 --- a/hacks/jitlib-hacks.scd +++ b/hacks/jitlib-hacks.scd @@ -63,6 +63,7 @@ Event.addEventType(\dirt, { ~latency = s.latency; ~delta = ~dur.value; ~s = ~s ? ~instrument; + d.value(currentEnvironment) }) ) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 4bb804b1..b2eb1080 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,14 +1,56 @@ +( + var sawfunc, supersawfunc; + supersawfunc = {|voices| + {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound; + var panspread = spread; + var freqspread = detune; -( - { - var unison = ~unison.value; + if (voices < 2) { + panspread = 0; + }; + + sound = Splay.arFill(voices, {|i| + SawDPW.ar(basefreq * pow(2, StrudelUtils.getUnisonDetune(voices, freqspread, i) / 12), + iphase: TRand.kr(-1, 1, Impulse.kr(0)) + ) + },spread: panspread, level: 1, center: 0); + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + } + }; + + (2..10).do{|voices| + var name = "supersaw" ++ voices; + SynthDef.new(name, supersawfunc.value(voices)).add; + }; + + ~dirt.soundLibrary.addSynth(\supersaw, + (playInside: { |e| + ( + instrument: "supersaw" ++ clip(~unison.value, 1, 10), + out: ~out, + freq: ~freq, + amp: ~amp, + detune: ~detune, + spread: ~spread, + group: ~synthGroup + ).play + }) + ); - SynthDef(\sawtooth, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + sawfunc = { + {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = SawDPW.ar(freq: basefreq); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; + } + }; + + SynthDef.new(\supersaw1, sawfunc.value()).add; + SynthDef(\sawtooth, sawfunc.value()).add; SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); @@ -22,30 +64,5 @@ Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; - SynthDef(\supersaw, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq =130.8, speed=1, spread = 0.5, detune = 0.15| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound; - var voices = 7; - var panspread = spread; - var freqspread = detune; - var gain1 = sqrt(1 - panspread); - var gain2 = sqrt(panspread); - voices = clip(voices, 0, 100); - - if (voices < 1) { - panspread = 0; - }; - - sound = Splay.arFill(voices, {|i| - SawDPW.ar(basefreq * pow(2, StrudelUtils.getUnisonDetune(voices, freqspread, i) / 12), - iphase: TRand.kr(-1, 1, Impulse.kr(0)) - ) - },spread: panspread, level: 1, center: 0); - - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; - - }.value +) - -); From 9b852204a02d8af744dd3adb409e10eecfb17b69 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 29 Aug 2024 20:02:33 -0400 Subject: [PATCH 09/34] fixed scale ration of samples --- classes/DirtSoundLibrary.sc | 27 ++++++++++++++++++++++++++- library/strudel-synths.scd | 8 +++++--- synths/core-synths.scd | 2 +- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/classes/DirtSoundLibrary.sc b/classes/DirtSoundLibrary.sc index a3c4249e..6242eb65 100644 --- a/classes/DirtSoundLibrary.sc +++ b/classes/DirtSoundLibrary.sc @@ -31,6 +31,27 @@ DirtSoundLibrary { synthEvents.clear; this.freeAllSoundFiles; } + // extractParts { |str| + // // Regex to split the string into numeric and non-numeric parts + // str.collect { |part| + // part.isNumber ifTrue: { part.asInteger } ifFalse: { part } + // }; + // } + + // sortStringsAlphanumerically { |stringArray| + // stringArray.sort { |a, b| + // var partsA = this.extractParts.(a); + // var partsB = this.extractParts.(b); + + // partsA.zip(partsB).detect { |pair| + // var (partA, partB) = pair; + // partA < partB ifTrue: { ^-1 }; + // partA > partB ifTrue: { ^1 }; + // }; + + // 0 // They are equal + // }; + // } addBuffer { |name, buffer, appendToExisting = false, metaData| var event, index; @@ -182,7 +203,9 @@ DirtSoundLibrary { }; files = pathMatch(folderPath.standardizePath +/+ "*"); // dependent on operating system - if(sortFiles) { files.sort }; + if(sortFiles) { + files.sort; + }; if(files.notEmpty) { name = name.asSymbol; @@ -198,7 +221,9 @@ DirtSoundLibrary { filePaths.do { |filepath| try { + var buf, metaData; + buf = this.readSoundFile(filepath); if(buf.notNil) { metaData = this.readMetaData(filepath); diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index b2eb1080..3734af41 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -30,12 +30,14 @@ ~dirt.soundLibrary.addSynth(\supersaw, (playInside: { |e| ( - instrument: "supersaw" ++ clip(~unison.value, 1, 10), + instrument: "supersaw" ++ clip(~unison.value ? 5, 1, 10), out: ~out, freq: ~freq, + speed: ~speed, + accelerate: ~accelerate, amp: ~amp, - detune: ~detune, - spread: ~spread, + detune: ~detune ? ~n ? 0.18, + spread: ~spread ? 0.6, group: ~synthGroup ).play }) diff --git a/synths/core-synths.scd b/synths/core-synths.scd index b68076d2..a455606b 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -28,7 +28,7 @@ live coding them requires that you have your SuperDirt instance in an environmen var sound, rate, phase, sawrate, numFrames; // playback speed - rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps); + rate = Line.kr(speed, endSpeed, sustain) * (freq / 36.midicps); // sample phase // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard From 04bd40a66674076e55d249e2667c0bdfe2892bde Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 29 Aug 2024 23:17:30 -0400 Subject: [PATCH 10/34] need fix... --- classes/DirtEvent.sc | 5 --- classes/DirtOrbit.sc | 13 ++----- classes/DirtSoundLibrary.sc | 3 +- classes/StrudelUtils.sc | 24 ++++++++++++ library/strudel-synths.scd | 78 ++++++++++++++++++++++++++++++++++++- synths/core-modules.scd | 58 +++++++++++++-------------- synths/core-synths.scd | 24 ++---------- used-parameters.scd | 1 + 8 files changed, 139 insertions(+), 67 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 54608c1c..dc609b07 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -13,14 +13,9 @@ DirtEvent { event.parent = orbit.defaultParentEvent; event.use { - // s and n stand for synth/sample and note/number ~s ?? { this.splitName }; - // if (~unison.notNil) { - // ~s = ~s ++ ~unison; - // }; - // unless orbit wide diversion returns something, we proceed ~diversion.(this) ?? { if(~s != \) { // backslash stands for do nothing diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index fa09ad6f..4032dd96 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -159,7 +159,7 @@ DirtOrbit { globalEffectBus.free; } -// if(~note.isNil) { if (~n.isNil) { 57 } { ~n } } { ~note } + makeDefaultParentEvent { defaultParentEvent = Event.make { @@ -175,11 +175,10 @@ DirtOrbit { ~unit = \r; ~n = \none; // sample number or note ~octave = 0; - ~midinote = #{ (~note ? ~n) + (~octave * 12) }; - ~freq = #{ ~midinote.value.midicps }; + ~midinote = #{ ~note ? ~n + (~octave * 12) }; + ~freq = #{ ~midinote.value.midicps }; ~dur = 1.0; ~delta = #{ ~dur.value }; - ~latency = 0.0; ~lag = 0.0; ~length = 1.0; @@ -189,12 +188,6 @@ DirtOrbit { ~amp = 0.4; ~fadeTime = 0.001; - // ~s = {if (~unison.notNil) { - // ~s ++ ~unison; - // } { - // ~s; - // } - // }; // values from the dirt bus diff --git a/classes/DirtSoundLibrary.sc b/classes/DirtSoundLibrary.sc index 6242eb65..d198c325 100644 --- a/classes/DirtSoundLibrary.sc +++ b/classes/DirtSoundLibrary.sc @@ -351,6 +351,7 @@ DirtSoundLibrary { makeEventForBuffer { |buffer, metaData| var baseFreq = 60.midicps; var baseFreqToMetaFreqRatio = metaData !? _[\baseFreqToMetaFreqRatio] ? 1.0; + ^( buffer: buffer.bufnum, bufferObject: buffer, @@ -369,7 +370,7 @@ DirtSoundLibrary { }, unitDuration: { buffer.duration * baseFreq / (~freq.value * ~metaDataTuneRatio.value) }, hash: buffer.identityHash, - note: 0 + note: 36 ) } diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index 8702ca9b..573a9c80 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -8,5 +8,29 @@ StrudelUtils { var amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); ^amount; } + *calculateCutoff {|cutoff=440, anchor=0, envamt=0, hold=0, holdtime, attack, decay, release, cutmin=20, cutmax=20000| + var offset = envamt.abs * anchor; + + var envmin = clip(2 ** (offset * -1) * cutoff, cutmin, cutmax); + var envmax = clip(2 ** (envamt.abs - offset) * cutoff, cutmin, cutmax); + + cutoff = EnvGen.ar( + Env.adsr( + attackTime: attack, + decayTime: decay, + releaseTime: release, + sustainLevel: hold, + peakLevel: envmax - envmin, + bias: envmin, + curve: -4 + ), + gate: Trig.ar(1, holdtime) + ); + ^cutoff; + } + *calculateResonance {|resonance=0| + // resonance = resonance * 0.05; + ^resonance.linexp(0, 1, 1, 0.001); + } } \ No newline at end of file diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 3734af41..3a8f5fbc 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,6 +1,6 @@ ( var sawfunc, supersawfunc; - + var numChannels = ~dirt.numChannels; supersawfunc = {|voices| {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); @@ -66,5 +66,81 @@ Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; + + //EFFECTS + + SynthDef("gain" ++ numChannels, { |out, gain=1.0 | + var signal = In.ar(out, numChannels) * gain; + ReplaceOut.ar(out, signal) + }, [\ir, \kr, \kr]).add; + + ~dirt.addModule('postgain', + { |dirtEvent| + dirtEvent.sendSynth("gain" ++ ~numChannels, + [ + gain: ~postgain, + out: ~out + ]) + + }, { ~cutoff.notNil }); + + SynthDef("strudel_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | + var signal = In.ar(out, numChannels); + cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); + resonance = StrudelUtils.calculateResonance(resonance); + signal = IIRFilter.ar(signal, cutoff, resonance); + ReplaceOut.ar(out, signal) + }, [\ir, \kr, \kr]).add; + + ~dirt.addModule('lpf', + { |dirtEvent| + dirtEvent.sendSynth("strudel_lpf" ++ ~numChannels, + [ + cutoff: ~cutoff, + resonance: ~resonance, + envamt: ~lpenv, + attack: {~lpattack.value ? ~attack.value}, + decay: {~lpdecay.value ? ~decay.value}, + hold: { ~lpsustain.value ? ~hold.value ? ~lpdecay.isNil}, + release: {~lprelease.value ? ~release.value}, + holdtime: ~sustain, + out: ~out + ]) + + }, { ~cutoff.notNil }); + + SynthDef("strudel_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve | + var signal = In.ar(out, numChannels); + var volenv = EnvGen.ar( + Env.adsr( + attackTime: attack, + decayTime: decay, + releaseTime: release, + sustainLevel: hold, + peakLevel: 1, + curve: curve + ), + gate: Trig.ar(1, holdtime) + ); + signal = signal * volenv; + ReplaceOut.ar(out, signal); + }, [\ir, \ir, \ir, \ir, \ir]).add; + + ~dirt.addModule('envelope', + { |dirtEvent| + dirtEvent.sendSynth('strudel_envelope' ++ ~numChannels, + [ + attack: ~attack, + decay: ~decay, + hold: { ~hold.value ? ~decay.isNil }, + holdtime: ~sustain, + release: ~release, + curve: {~curve.value ? -2}, + out: ~out + ]) + }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); + + ~dirt.orderModules(['dirt_gate','lpf','bpf','hpf','phaser','shape','crush','course','envelope']); + ) diff --git a/synths/core-modules.scd b/synths/core-modules.scd index 648c0b09..b4acc63a 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -147,22 +147,22 @@ this may be refacored later. }, { ~coarse.notNil and: { ~coarse > 1 } }); // coarse == 1 => full rate -~dirt.addModule('lpf', - { |dirtEvent| - dirtEvent.sendSynth("dirt_lpf" ++ ~numChannels, - [ - cutoff: ~cutoff, - resonance: ~resonance, - envamt: ~lpenv, - attack: {~lpattack.value ? ~attack.value}, - decay: {~lpdecay.value ? ~decay.value}, - hold: { ~lpsustain.value ? ~hold.value ? ~lpdecay.isNil}, - release: {~lprelease.value ? ~release.value}, - holdtime: ~sustain, - out: ~out - ]) - -}, { ~cutoff.notNil }); +// ~dirt.addModule('lpf', +// { |dirtEvent| +// dirtEvent.sendSynth("dirt_lpf" ++ ~numChannels, +// [ +// cutoff: ~cutoff, +// resonance: ~resonance, +// envamt: ~lpenv, +// attack: {~lpattack.value ? ~attack.value}, +// decay: {~lpdecay.value ? ~decay.value}, +// hold: { ~lpsustain.value ? ~hold.value ? ~lpdecay.isNil}, +// release: {~lprelease.value ? ~release.value}, +// holdtime: ~sustain, +// out: ~out +// ]) + +// }, { ~cutoff.notNil }); ~dirt.addModule('pshift', { |dirtEvent| @@ -175,19 +175,19 @@ this may be refacored later. ]) }, { ~psrate.notNil }); -~dirt.addModule('envelope', - { |dirtEvent| - dirtEvent.sendSynth('dirt_envelope' ++ ~numChannels, - [ - attack: ~attack, - decay: ~decay, - hold: { ~hold.value ? ~decay.isNil }, - holdtime: ~sustain, - release: ~release, - curve: {~curve.value ? -2}, - out: ~out - ]) -}, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); +// ~dirt.addModule('envelope', +// { |dirtEvent| +// dirtEvent.sendSynth('dirt_envelope' ++ ~numChannels, +// [ +// attack: ~attack, +// decay: ~decay, +// hold: { ~hold.value ? ~decay.isNil }, +// holdtime: ~sustain, +// release: ~release, +// curve: {~curve.value ? -2}, +// out: ~out +// ]) +// }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); ~dirt.addModule('grenvelo', { |dirtEvent| diff --git a/synths/core-synths.scd b/synths/core-synths.scd index a455606b..15f13a79 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -267,27 +267,9 @@ live coding them requires that you have your SuperDirt instance in an environmen SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | var signal = In.ar(out, numChannels); - var cutmax = SampleRate.ir / 2; - var cutmin = 20; - var offset = envamt.abs * anchor; - - var envmin = clip(2 ** (offset * -1) * cutoff, cutmin, cutmax); - var envmax = clip(2 ** (envamt.abs - offset) * cutoff, cutmin, cutmax); - - cutoff = EnvGen.ar( - Env.adsr( - attackTime: attack, - decayTime: decay, - releaseTime: release, - sustainLevel: hold, - peakLevel: envmax - envmin, - bias: envmin, - curve: -4 - ), - gate: Trig.ar(1, holdtime) - ); - - signal = RLPF.ar(signal, cutoff, resonance.linexp(0, 1, 1, 0.001)); + cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); + resonance = StrudelUtils.calculateResonance(resonance); + signal = IIRFilter.ar(signal, cutoff, resonance); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; diff --git a/used-parameters.scd b/used-parameters.scd index 5185425d..247ba1e5 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -34,6 +34,7 @@ clip sustain amp gain +postgain channel pan note From 88bfe2762df5801fbf63b7739c994f81648ce4f2 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 29 Aug 2024 23:46:33 -0400 Subject: [PATCH 11/34] flix clip duration --- classes/DirtEvent.sc | 36 ++++++++---------------------------- classes/DirtSoundLibrary.sc | 6 +++--- classes/StrudelUtils.sc | 8 ++++++-- library/strudel-synths.scd | 4 ++-- synths/core-synths.scd | 2 +- 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index dc609b07..00033ba7 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -122,16 +122,15 @@ DirtEvent { sustain = sustain ?? { delta = ~delta.value; - if(~clip.notNil) { - (delta / ~cps) * ~clip.value - } { - unitDuration = unitDuration ? delta; - loop !? { unitDuration = unitDuration * loop.abs }; - } + (delta / ~cps) * (~clip.value ? 1) + // if(~clip.notNil) { + // (delta / ~cps) * ~clip.value + // } { + // unitDuration = unitDuration ? delta; + // loop !? { unitDuration = unitDuration * loop.abs }; + // } }; - // sustain = sustain + release; - // end samples if sustain exceeds buffer duration // for every buffer, unitDuration is (and should be) defined. if(useUnit) { sustain = min(unitDuration, sustain) }; @@ -162,32 +161,13 @@ DirtEvent { args = args ?? { this.getMsgFunc(instrument).valueEnvir }; args.asControlInput.flop.do { |each| - - - // if (~unison.notNil) { - // instrument = instrument ++ ~unison; - - // }; - // if (instrument.asString == "supersaw") { - // server.sendMsg(\s_new , - // instrument ++ ~unison.value ? 2, - // -1, // no id - // 1, // add action: addToTail - // group, // send to group - // *each.asOSCArgArray // append all other args - // ) - // } { server.sendMsg(\s_new, instrument, -1, // no id 1, // add action: addToTail group, // send to group *each.asOSCArgArray // append all other args - ) - // } - - - + ) } } diff --git a/classes/DirtSoundLibrary.sc b/classes/DirtSoundLibrary.sc index d198c325..a397ccb7 100644 --- a/classes/DirtSoundLibrary.sc +++ b/classes/DirtSoundLibrary.sc @@ -349,9 +349,9 @@ DirtSoundLibrary { } makeEventForBuffer { |buffer, metaData| - var baseFreq = 60.midicps; + var baseFreq = StrudelUtils.baseNote().midicps; var baseFreqToMetaFreqRatio = metaData !? _[\baseFreqToMetaFreqRatio] ? 1.0; - + ^( buffer: buffer.bufnum, bufferObject: buffer, @@ -370,7 +370,7 @@ DirtSoundLibrary { }, unitDuration: { buffer.duration * baseFreq / (~freq.value * ~metaDataTuneRatio.value) }, hash: buffer.identityHash, - note: 36 + note: StrudelUtils.baseNote() ) } diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index 573a9c80..2f7138a7 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -32,5 +32,9 @@ StrudelUtils { // resonance = resonance * 0.05; ^resonance.linexp(0, 1, 1, 0.001); } - -} \ No newline at end of file + *baseNote { + ^36; + } + +} + diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 3a8f5fbc..776a8807 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -82,7 +82,7 @@ out: ~out ]) - }, { ~cutoff.notNil }); + }, { ~postgain.notNil }); SynthDef("strudel_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | var signal = In.ar(out, numChannels); @@ -140,7 +140,7 @@ ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['dirt_gate','lpf','bpf','hpf','phaser','shape','crush','course','envelope']); + ~dirt.orderModules(['dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','envelope','postgain']); ) diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 15f13a79..78c6189b 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -28,7 +28,7 @@ live coding them requires that you have your SuperDirt instance in an environmen var sound, rate, phase, sawrate, numFrames; // playback speed - rate = Line.kr(speed, endSpeed, sustain) * (freq / 36.midicps); + rate = Line.kr(speed, endSpeed, sustain) * (freq / StrudelUtils.baseNote().midicps); // sample phase // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard From e6350ab24736d8d3c5df90f21034541f6c9fbfe0 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 30 Aug 2024 10:58:48 -0400 Subject: [PATCH 12/34] add distortion --- library/default-effects-extra.scd | 6 +++--- library/strudel-synths.scd | 23 +++++++++++++++++++++++ used-parameters.scd | 2 ++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/library/default-effects-extra.scd b/library/default-effects-extra.scd index 52c315a9..6925fdb0 100644 --- a/library/default-effects-extra.scd +++ b/library/default-effects-extra.scd @@ -152,14 +152,14 @@ DEFAULT EFFECTS EXTRA }, [\ir]).add; // A crunchy distortion with a lot of high harmonics, the only parameter is `distort` - ~dirt.addModule('distort', { |dirtEvent| + ~dirt.addModule('distort2', { |dirtEvent| dirtEvent.sendSynth("dirt_distort" ++ ~dirt.numChannels, [ - distort: ~distort, + distort: ~distort2, out: ~out ] ) - }, { ~distort.notNil }); + }, { ~distort2.notNil }); SynthDef("dirt_distort" ++ ~dirt.numChannels, { |out, distort = 0| var signal, mod; diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 776a8807..7e9822a4 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -109,6 +109,29 @@ }, { ~cutoff.notNil }); + + SynthDef("strudel_distort" ++ numChannels, { |out, shape = 0, postgain = 1| + + var signal = In.ar(out, numChannels), amp = 1; + + shape = exp(shape) - 1; + // shape = min(shape, 1.0 - 4e-10); // avoid division by zero + postgain = clip(postgain, 0.001, 1); + + signal = ((1 + shape) * signal / (1 + (shape * abs(signal)))) * postgain; + ReplaceOut.ar(out, signal * amp) + }, [\ir, \kr]).add; + + ~dirt.addModule('distort', + { |dirtEvent| + dirtEvent.sendSynth('strudel_distort' ++ ~numChannels, + [ + shape: ~distort, + postgain: ~distortvol ? 1, + out: ~out + ]) + }, { ~distort.notNil }); + SynthDef("strudel_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve | var signal = In.ar(out, numChannels); var volenv = EnvGen.ar( diff --git a/used-parameters.scd b/used-parameters.scd index 247ba1e5..bb33b6a5 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -98,6 +98,8 @@ tremolorate tremolodepth phaserrate phaserdepth +distort +distortvol tilt plat From e60f514dab953cc90025f1b795f39bdc8838f2af Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 30 Aug 2024 11:01:10 -0400 Subject: [PATCH 13/34] update doc --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 341f2867..8b103763 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# SuperDirt +# SuperTweak +This is a fork of superdirt that is intended to play well with Strudel.cc SuperCollider implementation of the Dirt sampler, originally designed for the [TidalCycles](https://github.com/tidalcycles/tidal) @@ -32,7 +33,7 @@ along with this library. If not, see . ## Installation from SuperCollider ``` -include("SuperDirt"); +in interpreter options in supercollider, include the path to this repo ``` Note: this also automatically installs the DirtSamples quark, which contains a large collection of sound files. It downloads them as a zip file. Sometimes, git fails to unpack these samples and they don't get listed. In this case, you have to unpack them "manually". From 7a0e601ada91f85e3b1c968bb4e076b6daf8a802 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 30 Aug 2024 18:48:29 -0400 Subject: [PATCH 14/34] fix stupid null handling bug with supersaw :) --- classes/DirtEventTypes.sc | 5 +++-- classes/DirtOrbit.sc | 3 ++- classes/DirtSoundLibrary.sc | 3 +-- library/strudel-synths.scd | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/classes/DirtEventTypes.sc b/classes/DirtEventTypes.sc index 3830b726..acbb0a48 100644 --- a/classes/DirtEventTypes.sc +++ b/classes/DirtEventTypes.sc @@ -44,7 +44,8 @@ DirtEventTypes { var freq, lag, sustain; var args, midiout, hasGate, midicmd, latency, chan; var sendNRPN, schedmidi, schedmidicmd, donecmd; - var hasNote = (~n != \none or: {~note.notNil}); + // var hasNote = (~n != \none or: {~note.notNil}); + var hasNote = (~n.notNil or: {~note.notNil}); var midiCommandPending = ~midicmd.notNil; var nrpnMSB, nrpnLSB, valMSB, valLSB; var ctlNum, control, num, val, note; @@ -108,7 +109,7 @@ DirtEventTypes { if (hasNote) { freq = ~freq.value; - ~midinote = (freq.cpsmidi).round(1).asInteger; + ~midinote = ((freq.cpsmidi).round(1) ? 0).asInteger; // Assume aftertouch means no noteOn, for now.. if(~polyTouch.notNil) { val = ~polyTouch; diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 4032dd96..bf4ddd82 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -173,7 +173,8 @@ DirtOrbit { ~overgain = 0.0; ~cut = 0.0; ~unit = \r; - ~n = \none; // sample number or note + ~n = nil; + // ~n = \none; // sample number or note ~octave = 0; ~midinote = #{ ~note ? ~n + (~octave * 12) }; ~freq = #{ ~midinote.value.midicps }; diff --git a/classes/DirtSoundLibrary.sc b/classes/DirtSoundLibrary.sc index a397ccb7..bb11c780 100644 --- a/classes/DirtSoundLibrary.sc +++ b/classes/DirtSoundLibrary.sc @@ -327,8 +327,7 @@ DirtSoundLibrary { ^event } { - // the index may be \none (a Symbol), but this converts it to 0 - event = allEvents.wrapAt(index.asInteger); + event = allEvents.wrapAt((index ? 0).asInteger); }; if(doNotReadYet and: { event.notNil and: { event[\notYetRead] ? false } }) { diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 7e9822a4..2a6e9ba6 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -36,7 +36,7 @@ speed: ~speed, accelerate: ~accelerate, amp: ~amp, - detune: ~detune ? ~n ? 0.18, + detune: ~detune.value ? ~n.value ? 0.18, spread: ~spread ? 0.6, group: ~synthGroup ).play From cbbe8baedc086470f809a6ff68cb5294e39dbb4a Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 30 Aug 2024 22:29:08 -0400 Subject: [PATCH 15/34] fix sound order --- classes/DirtOrbit.sc | 2 +- hacks/pitch-model-from-tidal.scd | 3 ++- library/strudel-synths.scd | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index bf4ddd82..8801c1ea 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -176,7 +176,7 @@ DirtOrbit { ~n = nil; // ~n = \none; // sample number or note ~octave = 0; - ~midinote = #{ ~note ? ~n + (~octave * 12) }; + ~midinote = #{ (~note ? ~n ? StrudelUtils.baseNote()) + (~octave * 12) }; ~freq = #{ ~midinote.value.midicps }; ~dur = 1.0; ~delta = #{ ~dur.value }; diff --git a/hacks/pitch-model-from-tidal.scd b/hacks/pitch-model-from-tidal.scd index 60564dd3..ce796812 100644 --- a/hacks/pitch-model-from-tidal.scd +++ b/hacks/pitch-model-from-tidal.scd @@ -47,7 +47,8 @@ let degree = pF "degree" var scale, tuning; pitchEvent.use { ~freq = { - if(~n != 0) { ~note = ~n }; // interpret n as note (might be also degree) + if(~n.notNil) { ~note = ~n }; // interpret n as note (might be also degree) + // if(~n != 0) { ~note = ~n }; // interpret n as note (might be also degree) ~scaleName !? { scale = Scale.at(~scaleName); scale !? { diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 2a6e9ba6..98b44a75 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -163,7 +163,7 @@ ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','envelope','postgain']); + ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','envelope','postgain']); ) From cda96c6181b79a670625539925cdeef5b6e396e6 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 31 Aug 2024 13:09:42 -0400 Subject: [PATCH 16/34] fix release sample repeat bug and sample clipping behavior --- classes/DirtEvent.sc | 25 +++++++++++++++++++------ classes/DirtOrbit.sc | 5 ++++- classes/StrudelUtils.sc | 4 ++++ library/strudel-synths.scd | 1 + synths/core-modules.scd | 1 + synths/core-synths.scd | 24 ++++++++++++++++++++---- 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 00033ba7..366067b4 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -83,7 +83,7 @@ DirtEvent { var accelerate = ~accelerate.value; var avgSpeed, endSpeed; var useUnit; - var release = ~release.value ? 0.0; + ~release = ~release.value ? 0.01; ~freq = ~freq.value; unitDuration = ~unitDuration.value; @@ -122,7 +122,13 @@ DirtEvent { sustain = sustain ?? { delta = ~delta.value; - (delta / ~cps) * (~clip.value ? 1) + if (useUnit and: ~clip.isNil) { + unitDuration = unitDuration ? delta; + loop !? { unitDuration = unitDuration * loop.abs }; + } { + (delta / ~cps) * (~clip.value ? 1) + }; + // if(~clip.notNil) { // (delta / ~cps) * ~clip.value // } { @@ -130,15 +136,21 @@ DirtEvent { // loop !? { unitDuration = unitDuration * loop.abs }; // } }; + // end samples if sustain exceeds buffer duration // for every buffer, unitDuration is (and should be) defined. - if(useUnit) { sustain = min(unitDuration, sustain) }; + // if(useUnit) { sustain = min(unitDuration, sustain) }; - ~fadeTime = min(~fadeTime.value, sustain * 0.19098); - ~fadeInTime = if(~begin != 0) { ~fadeTime } { 0.0 }; + + // ~fadeTime = min(~fadeTime.value, sustain * 0.19098); + // ~fadeTime = ~fadeTime.value ? .001; + // ~fadeInTime = if(~begin != 0) { ~fadeTime } { 0.0 }; if (~timescale.notNil) {sustain = sustain * ~timescale }; - ~sustain = sustain - (~fadeTime + ~fadeInTime); + ~totalDuration = if (useUnit) {min(unitDuration, sustain + ~release)} {sustain + ~release}; + // ~sustain = sustain - (~fadeTime + ~fadeInTime); + ~sustain = sustain; + ~speed = speed; ~endSpeed = endSpeed; @@ -186,6 +198,7 @@ DirtEvent { sample: ~hash, // required for the cutgroup mechanism cut: ~cut.abs, release: ~release, + totalDuration: ~totalDuration, sustain: ~sustain, // after sustain, free all synths and group fadeInTime: ~fadeInTime, // fade in fadeTime: ~fadeTime // fade out diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 8801c1ea..72a8c538 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -174,6 +174,9 @@ DirtOrbit { ~cut = 0.0; ~unit = \r; ~n = nil; + // ~release = 0.001; + // ~totalDuration = #{~sustain.value + ~release.value}; + // ~sustain = #{~sustain.value + ~release.value}; // ~n = \none; // sample number or note ~octave = 0; ~midinote = #{ (~note ? ~n ? StrudelUtils.baseNote()) + (~octave * 12) }; @@ -187,7 +190,7 @@ DirtOrbit { ~dry = 0.0; ~lock = 0; // if set to 1, syncs delay times with cps - ~amp = 0.4; + ~amp = 0.6; ~fadeTime = 0.001; diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index 2f7138a7..eaadade4 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -35,6 +35,10 @@ StrudelUtils { *baseNote { ^36; } + //makeup gain for sample buffer + *sampleGain { + ^1.7; + } } diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 98b44a75..d4fd5072 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -17,6 +17,7 @@ iphase: TRand.kr(-1, 1, Impulse.kr(0)) ) },spread: panspread, level: 1, center: 0); + sound = sound * 1.2; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } diff --git a/synths/core-modules.scd b/synths/core-modules.scd index b4acc63a..8b56fbf6 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -45,6 +45,7 @@ this may be refacored later. speed: ~speed, freq: ~freq * ~metaDataTuneRatio.value, endSpeed: ~endSpeed, + totalDuration: ~totalDuration, begin: ~begin, end: ~end, pan: ~pan, diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 78c6189b..74b99db7 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -16,20 +16,27 @@ live coding them requires that you have your SuperDirt instance in an environmen ( { var numChannels = ~dirt.numChannels; + // var getPlaybackSpeed; + // getPlaybackSpeed = {|sustain, | + + // } + // write variants for different sample buffer sizes (1..SuperDirt.maxSampleNumChannels).do { |sampleNumChannels| var name = format("dirt_sample_%_%", sampleNumChannels, numChannels); - SynthDef(name, { |out, bufnum, sustain = 1, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0| + SynthDef(name, { |out, bufnum, totalDuration = 0, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0| var sound, rate, phase, sawrate, numFrames; + // playback speed - rate = Line.kr(speed, endSpeed, sustain) * (freq / StrudelUtils.baseNote().midicps); + rate = Line.kr(speed, endSpeed, totalDuration) * (freq / StrudelUtils.baseNote().midicps); + // sample phase // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard @@ -46,6 +53,7 @@ live coding them requires that you have your SuperDirt instance in an environmen loop: 0, interpolation: 4 // cubic interpolation ); + sound = sound * StrudelUtils.sampleGain(); sound = DirtPan.ar(sound, numChannels, pan); @@ -69,6 +77,7 @@ live coding them requires that you have your SuperDirt instance in an environmen // playback speed rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps); + // sample phase // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard //phase = Sweep.ar(1, rate * BufSampleRate.ir(bufnum)) + (BufFrames.ir(bufnum) * begin); @@ -91,6 +100,7 @@ live coding them requires that you have your SuperDirt instance in an environmen env = EnvGen.kr(Env.linen(0, sustain, 0)); // todo: check if control rate smoothens (shouldn't) sound = sound * env; + sound = sound * StrudelUtils.sampleGain(); sound = DirtPan.ar(sound, numChannels, pan); @@ -113,6 +123,7 @@ live coding them requires that you have your SuperDirt instance in an environmen // playback speed rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps); + // sample phase // BufSampleRate adjusts the rate if the sound file doesn't have the same rate as the soundcard //phase = Sweep.ar(1, rate * BufSampleRate.ir(bufnum)) + (BufFrames.ir(bufnum) * begin); @@ -155,6 +166,7 @@ live coding them requires that you have your SuperDirt instance in an environmen interpolation: 4 // cubic interpolation ); sound = (sound0 + sound1) / window.sum; + sound = sound * StrudelUtils.sampleGain(); sound = DirtPan.ar(sound, numChannels, pan); @@ -174,10 +186,14 @@ live coding them requires that you have your SuperDirt instance in an environmen // the monitor does the mixing and zeroing of the busses for each sample grain // so that they can all play in one bus - SynthDef("dirt_gate" ++ numChannels, { |out, in, sustain = 1, release = 0, fadeInTime = 0.001, fadeTime = 0.001, amp = 1, gain = 1, overgain = 0| + SynthDef("dirt_gate" ++ numChannels, { |out, in, totalDuration = 0, fadeInTime = 0.001, fadeTime = 0.001, amp = 1, gain = 1, overgain = 0| var signal = In.ar(in, numChannels); // doneAction: 14: free surrounding group and all nodes - var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain + release, fadeTime], \sin), doneAction: 14); + var holdtime = totalDuration - (fadeInTime + fadeTime); + + var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, holdtime, fadeTime], \sin), doneAction: 14); + + // var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain + release, fadeTime], \sin), doneAction: 14); amp = amp * (gain + overgain); signal = signal * env * amp * DirtGateCutGroup.ar(fadeTime, doneAction: 14); // this takes the signal and offsets it so it matches precisely onto the sample From fd6c62416502f11a808ce63032300d9d418fcf12 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 31 Aug 2024 16:51:03 -0400 Subject: [PATCH 17/34] add remaining filter envelopes --- library/strudel-synths.scd | 52 ++++++++++++++++++++++++++++++++++++++ synths/core-modules.scd | 36 +++++++++++++------------- synths/core-synths.scd | 24 ++++++++---------- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index d4fd5072..77927560 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -98,6 +98,7 @@ dirtEvent.sendSynth("strudel_lpf" ++ ~numChannels, [ cutoff: ~cutoff, + anchor: ~anchor, resonance: ~resonance, envamt: ~lpenv, attack: {~lpattack.value ? ~attack.value}, @@ -110,6 +111,57 @@ }, { ~cutoff.notNil }); + SynthDef("strudel_hpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime| + var signal = In.ar(out, numChannels); + cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); + resonance = StrudelUtils.calculateResonance(resonance); + signal = RHPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), resonance); + ReplaceOut.ar(out, signal) + }, [\ir, \kr, \kr]).add; + + ~dirt.addModule('hpf', + { |dirtEvent| + dirtEvent.sendSynth("strudel_hpf" ++ ~numChannels, + [ + cutoff: ~hcutoff, + anchor: ~anchor, + resonance: ~hresonance, + envamt: ~hpenv, + attack: {~hpattack.value ? ~attack.value}, + decay: {~hpdecay.value ? ~decay.value}, + hold: { ~hpsustain.value ? ~hold.value ? ~hpdecay.isNil}, + release: {~hprelease.value ? ~release.value}, + holdtime: ~sustain, + out: ~out + ]) + + }, { ~hcutoff.notNil }); + + SynthDef("strudel_bpf" ++ numChannels, { |out, cutoff=440, resonance=0, attack, hold, decay, envamt=0, anchor=0, release, holdtime| + var signal = In.ar(out, numChannels); + cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); + resonance = StrudelUtils.calculateResonance(resonance); + signal = BPF.ar(signal, cutoff, 1/resonance) * max(resonance, 1.0); + ReplaceOut.ar(out, signal) + }, [\ir, \kr, \kr]).add; + + ~dirt.addModule('bpf', + { |dirtEvent| + dirtEvent.sendSynth("strudel_bpf" ++ ~numChannels, + [ + cutoff: ~bandf, + anchor: ~anchor, + resonance: ~bandq, + envamt: ~bpenv, + attack: {~bpattack.value ? ~attack.value}, + decay: {~bpdecay.value ? ~decay.value}, + hold: { ~bpsustain.value ? ~hold.value ? ~bpdecay.isNil}, + release: {~bprelease.value ? ~release.value}, + holdtime: ~sustain, + out: ~out + ]) + + }, { ~bandf.notNil }); SynthDef("strudel_distort" ++ numChannels, { |out, shape = 0, postgain = 1| diff --git a/synths/core-modules.scd b/synths/core-modules.scd index 8b56fbf6..1e35069d 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -105,27 +105,27 @@ this may be refacored later. }, { ~shape.notNil }); -~dirt.addModule('hpf', - { |dirtEvent| - dirtEvent.sendSynth("dirt_hpf" ++ ~numChannels, - [ - hcutoff: ~hcutoff, - hresonance: ~hresonance, - out: ~out - ]) +// ~dirt.addModule('hpf', +// { |dirtEvent| +// dirtEvent.sendSynth("dirt_hpf" ++ ~numChannels, +// [ +// hcutoff: ~hcutoff, +// hresonance: ~hresonance, +// out: ~out +// ]) -}, { ~hcutoff.notNil }); +// }, { ~hcutoff.notNil }); -~dirt.addModule('bpf', - { |dirtEvent| - dirtEvent.sendSynth("dirt_bpf" ++ ~numChannels, - [ - bandqf: ~bandf, - bandq: ~bandq, - out: ~out - ]) +// ~dirt.addModule('bpf', +// { |dirtEvent| +// dirtEvent.sendSynth("dirt_bpf" ++ ~numChannels, +// [ +// bandqf: ~bandf, +// bandq: ~bandq, +// out: ~out +// ]) -}, { ~bandf.notNil }); +// }, { ~bandf.notNil }); ~dirt.addModule('crush', { |dirtEvent| diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 74b99db7..7547bc2c 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -16,13 +16,7 @@ live coding them requires that you have your SuperDirt instance in an environmen ( { var numChannels = ~dirt.numChannels; - // var getPlaybackSpeed; - // getPlaybackSpeed = {|sustain, | - - // } - - // write variants for different sample buffer sizes (1..SuperDirt.maxSampleNumChannels).do { |sampleNumChannels| @@ -34,6 +28,7 @@ live coding them requires that you have your SuperDirt instance in an environmen // playback speed + rate = Line.kr(speed, endSpeed, totalDuration) * (freq / StrudelUtils.baseNote().midicps); @@ -70,12 +65,13 @@ live coding them requires that you have your SuperDirt instance in an environmen var name = format("dirt_sample_long_%_%", sampleNumChannels, numChannels); - SynthDef(name, { |out, bufnum, sustain = 1, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0| + SynthDef(name, { |out, bufnum, totalDuration = 1, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0| var sound, rate, env, startPos, numFrames; // playback speed - rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps); + rate = Line.kr(speed, endSpeed, totalDuration) * (freq / StrudelUtils.baseNote().midicps); + // sample phase @@ -97,7 +93,7 @@ live coding them requires that you have your SuperDirt instance in an environmen loop: 0 ); - env = EnvGen.kr(Env.linen(0, sustain, 0)); // todo: check if control rate smoothens (shouldn't) + env = EnvGen.kr(Env.linen(0, totalDuration, 0)); // todo: check if control rate smoothens (shouldn't) sound = sound * env; sound = sound * StrudelUtils.sampleGain(); @@ -115,13 +111,14 @@ live coding them requires that you have your SuperDirt instance in an environmen var name = format("dirt_stretchsample_%_%", sampleNumChannels, numChannels); - SynthDef(name, { |out, bufnum, sustain = 1, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0, timescale = 1, timescalewin = 1| + SynthDef(name, { |out, bufnum, totalDuration, begin = 0, end = 1, speed = 1, endSpeed = 1, freq = 440, pan = 0, timescale = 1, timescalewin = 1| var sound, rate, phase, sawrate, numFrames, index, windowIndex, window, timescaleStep; var sound0, sound1, windowSize, nSteps; // playback speed - rate = Line.kr(speed, endSpeed, sustain) * (freq / 60.midicps); + rate = Line.kr(speed, endSpeed, totalDuration) * (freq / StrudelUtils.baseNote().midicps); + // sample phase @@ -209,10 +206,9 @@ live coding them requires that you have your SuperDirt instance in an environmen */ - SynthDef("dirt_out" ++ numChannels, { |out, to, sustain = 1, fadeInTime = 0.001, fadeTime = 0.001, through = 0, amp = 1| + SynthDef("dirt_out" ++ numChannels, { |out, to, totalDuration, fadeInTime = 0.001, fadeTime = 0.001, through = 0, amp = 1| var signal = In.ar(out, numChannels); - var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain, fadeTime], \sin)); - + var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, totalDuration - (fadeInTime + fadeTime), fadeTime], \sin)); Out.ar(to, signal * env * amp); ReplaceOut.ar(out, signal * through); }, [\ir, \ir, \ir, \ir, \ir, \ir, \kr]).add; // amp can be modulated From 36be99b293fc75ce375c1de261f0bb9ddfca02a5 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 1 Sep 2024 14:54:24 -0400 Subject: [PATCH 18/34] kinda working --- classes/GlobalDirtEffect.sc | 1 - classes/SuperDirt.sc | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/classes/GlobalDirtEffect.sc b/classes/GlobalDirtEffect.sc index 60962347..0d234af5 100644 --- a/classes/GlobalDirtEffect.sc +++ b/classes/GlobalDirtEffect.sc @@ -30,7 +30,6 @@ GlobalDirtEffect { ) } - release { |releaseTime = 0.2| if(synth.notNil) { synth.server.sendBundle(nil, diff --git a/classes/SuperDirt.sc b/classes/SuperDirt.sc index 0f13700e..0d7a33ca 100644 --- a/classes/SuperDirt.sc +++ b/classes/SuperDirt.sc @@ -282,6 +282,7 @@ SuperDirt { playFunc = { |msg, time, tidalAddr| var latency = time - thisThread.seconds; var event = (), orbit, index; + if(dropWhen.value.not) { if(latency > maxLatency) { "The scheduling delay is too long. Your networks clocks may not be in sync".warn; @@ -292,6 +293,7 @@ SuperDirt { event.putPairs(msg[1..]); receiveAction.value(event); index = event[\orbit] ? 0; + // msg.postln; if(warnOutOfOrbit and: { index >= orbits.size } or: { index < 0 }) { "SuperDirt: event falls out of existing orbits, index (%)".format(index).warn From 368613d4fab0b541ae088b6602fada2354b68f73 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 2 Sep 2024 17:16:30 -0400 Subject: [PATCH 19/34] phaser and compressor --- classes/SuperDirt.sc | 4 +-- library/strudel-synths.scd | 71 +++++++++++++++++++++++++++++++++++++- synths/core-modules.scd | 18 +++++----- used-parameters.scd | 5 +++ 4 files changed, 85 insertions(+), 13 deletions(-) diff --git a/classes/SuperDirt.sc b/classes/SuperDirt.sc index 0d7a33ca..14a11fbd 100644 --- a/classes/SuperDirt.sc +++ b/classes/SuperDirt.sc @@ -281,8 +281,7 @@ SuperDirt { playFunc = { |msg, time, tidalAddr| var latency = time - thisThread.seconds; - var event = (), orbit, index; - + var event = (), orbit, index; if(dropWhen.value.not) { if(latency > maxLatency) { "The scheduling delay is too long. Your networks clocks may not be in sync".warn; @@ -293,7 +292,6 @@ SuperDirt { event.putPairs(msg[1..]); receiveAction.value(event); index = event[\orbit] ? 0; - // msg.postln; if(warnOutOfOrbit and: { index >= orbits.size } or: { index < 0 }) { "SuperDirt: event falls out of existing orbits, index (%)".format(index).warn diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 77927560..17571d15 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -185,6 +185,75 @@ ]) }, { ~distort.notNil }); + SynthDef("strudel_phaser" ++ numChannels, { |out, phaserrate, phaserdepth, phasercenter, phasersweep, phaserstages, phaseoffset| + var signal, phaserwave; + var modgain = phasersweep; + var fOffset = 0; + var cutoff; + var mod = LFTri.kr(phaserrate, iphase: phaseoffset).range(-1, 1); + mod = (mod * modgain) + phasercenter; + + signal = In.ar(out, numChannels); + (1..10).do{|i| + if (i <= numChannels){ + cutoff = clip(mod + fOffset, 20, SampleRate.ir / 2 ); + signal = SVF.ar( + signal, + cutoff: cutoff, + res: phaserdepth, + notch: 0.25, + ); + fOffset = fOffset + 282; + }; + + }; + + ReplaceOut.ar(out, signal); + }, [\ir, \kr]).add; + + + + ~dirt.addModule('phaser', + { |dirtEvent| + dirtEvent.sendSynth('strudel_phaser' ++ ~numChannels, + [ + phaserrate: ~phaserrate, + phaserdepth: ~phaserdepth ? 0.0, + phasercenter: ~phasercenter ? 2800, + phasersweep: ~phasersweep ? 2000, + phaserstages: ~phaserstages ? 2, + phaseoffset: (((~cycle ? 1 / ~cps ? 0.5) * ~phaserrate) % 1) * 4, + out: ~out + ]) + }, { ~phaserrate.notNil }); + + SynthDef("strudel_compressor" ++ numChannels, { |out, threshold = 0, ratio = 0.25, knee = 8, attack = 0.1, release = 0.1| + var signal = In.ar(out, numChannels), amp = 1; + threshold = clip(threshold, 0.01, 100); + + signal = Compander.ar(signal, signal, + thresh: threshold, + slopeBelow: knee, + slopeAbove: ratio, + clampTime: attack, + relaxTime: release + ); + ReplaceOut.ar(out, signal * amp) + }, [\ir, \kr]).add; + + ~dirt.addModule('compressor', + { |dirtEvent| + dirtEvent.sendSynth('strudel_compressor' ++ ~numChannels, + [ + threshold: ~compressor ? -3, + ratio: ~compressorRatio ? 0.25, + knee: ~compressorKnee ? 0.8, + attack: ~compressorAttack ? 0.01, + release: ~compressorRelease ? 0.01, + out: ~out + ]) + }, { ~compressor.notNil }); + SynthDef("strudel_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve | var signal = In.ar(out, numChannels); var volenv = EnvGen.ar( @@ -216,7 +285,7 @@ ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','envelope','postgain']); + ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','compressor','distort','envelope','postgain']); ) diff --git a/synths/core-modules.scd b/synths/core-modules.scd index 1e35069d..9e05fc4c 100644 --- a/synths/core-modules.scd +++ b/synths/core-modules.scd @@ -214,14 +214,14 @@ this may be refacored later. }, { ~tremolorate.notNil }); // Phaser audio DSP effect declaration -~dirt.addModule('phaser', - { |dirtEvent| - dirtEvent.sendSynth('dirt_phaser' ++ ~numChannels, - [ - phaserrate: ~phaserrate, - phaserdepth: ~phaserdepth, - out: ~out - ]) -}, { ~phaserrate.notNil }); +// ~dirt.addModule('phaser', +// { |dirtEvent| +// dirtEvent.sendSynth('dirt_phaser' ++ ~numChannels, +// [ +// phaserrate: ~phaserrate, +// phaserdepth: ~phaserdepth, +// out: ~out +// ]) +// }, { ~phaserrate.notNil }); ); diff --git a/used-parameters.scd b/used-parameters.scd index bb33b6a5..cc5be305 100644 --- a/used-parameters.scd +++ b/used-parameters.scd @@ -100,6 +100,11 @@ phaserrate phaserdepth distort distortvol +compressor +compressorRatio +compressorKnee +compressorAttack +compressorRelease tilt plat From f32c1b9e4a848f8471cfdfb6623fafc8bd914d24 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 2 Sep 2024 17:35:51 -0400 Subject: [PATCH 20/34] fix phaser --- library/strudel-synths.scd | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 17571d15..07967153 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -185,30 +185,35 @@ ]) }, { ~distort.notNil }); - SynthDef("strudel_phaser" ++ numChannels, { |out, phaserrate, phaserdepth, phasercenter, phasersweep, phaserstages, phaseoffset| - var signal, phaserwave; + SynthDef("strudel_phaser" ++ numChannels, { |out, phaserrate, phaserdepth = 0.5, phasercenter, phasersweep, phaserstages, phaseoffset| + var signal = In.ar(out, numChannels); var modgain = phasersweep; var fOffset = 0; var cutoff; var mod = LFTri.kr(phaserrate, iphase: phaseoffset).range(-1, 1); + var modsignal = signal; + // var fade = (2 * phaserdepth) -1; + mod = (mod * modgain) + phasercenter; + - signal = In.ar(out, numChannels); - (1..10).do{|i| - if (i <= numChannels){ + + (1..3).do{|i| + // if (i <= phaserstages){ cutoff = clip(mod + fOffset, 20, SampleRate.ir / 2 ); - signal = SVF.ar( - signal, + modsignal = SVF.ar( + modsignal, cutoff: cutoff, - res: phaserdepth, - notch: 0.25, + lowpass:0, + res: 1 - phaserdepth, + notch: 1, ); fOffset = fOffset + 282; - }; + // }; }; - - ReplaceOut.ar(out, signal); + + ReplaceOut.ar(out, modsignal); }, [\ir, \kr]).add; @@ -219,7 +224,7 @@ [ phaserrate: ~phaserrate, phaserdepth: ~phaserdepth ? 0.0, - phasercenter: ~phasercenter ? 2800, + phasercenter: ~phasercenter ? 2700, phasersweep: ~phasersweep ? 2000, phaserstages: ~phaserstages ? 2, phaseoffset: (((~cycle ? 1 / ~cps ? 0.5) * ~phaserrate) % 1) * 4, From 561903a1e4bd1e5fff59d655e47977765e3ab09a Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 2 Sep 2024 22:15:27 -0400 Subject: [PATCH 21/34] phase_depth_min --- library/strudel-synths.scd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 07967153..9373b1e5 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -223,7 +223,7 @@ dirtEvent.sendSynth('strudel_phaser' ++ ~numChannels, [ phaserrate: ~phaserrate, - phaserdepth: ~phaserdepth ? 0.0, + phaserdepth: ~phaserdepth ? 0.75, phasercenter: ~phasercenter ? 2700, phasersweep: ~phasersweep ? 2000, phaserstages: ~phaserstages ? 2, @@ -290,7 +290,7 @@ ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','phaser','shape','crush','coarse','compressor','distort','envelope','postgain']); + ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','shape','crush','coarse','phaser','compressor','distort','envelope','postgain']); ) From 7072d239b65a5955d6305f23a933a766be364a81 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 3 Sep 2024 00:03:22 -0400 Subject: [PATCH 22/34] add noise --- library/strudel-synths.scd | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 9373b1e5..b833345c 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -67,6 +67,19 @@ Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; + SynthDef(\white, {|out, pan| + var sound = WhiteNoise.ar(mul:0.5); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + SynthDef(\brown, {|out, pan| + var sound = BrownNoise.ar(mul:0.5); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + SynthDef(\pink, {|out, pan| + var sound = PinkNoise.ar(mul:0.5); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + //EFFECTS From 2859c80195e458c8c08b50608c4ad2cb5b8746f7 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Thu, 5 Sep 2024 23:58:42 -0400 Subject: [PATCH 23/34] add pulse oscillator --- library/strudel-synths.scd | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index b833345c..6f4fe478 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -61,6 +61,19 @@ Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; + SynthDef(\pulse, {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var width = z1; + var modspeed = z2; + var moddepth = z3; + var phaseoffset = (((cycle / cps) * modspeed) % 1) * 4; + + var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; + var sound = Pulse.ar(basefreq, width: clip(mod + width,0.01, 0.99)); + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + }).add; + SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = LFTri.ar(basefreq); From 287947f4f31ac27e768b8b505c77bf66867296ef Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 7 Sep 2024 14:25:01 -0400 Subject: [PATCH 24/34] superpulse --- classes/StrudelUtils.sc | 4 -- library/strudel-synths.scd | 98 +++++++++++++++++++++++++++++++++----- synths/core-synths.scd | 1 - 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index eaadade4..fe5bc4c2 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -28,10 +28,6 @@ StrudelUtils { ); ^cutoff; } - *calculateResonance {|resonance=0| - // resonance = resonance * 0.05; - ^resonance.linexp(0, 1, 1, 0.001); - } *baseNote { ^36; } diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 6f4fe478..3540c079 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,5 +1,5 @@ ( - var sawfunc, supersawfunc; + var sawfunc, supersawfunc, pulsefunc, superpulsefunc; var numChannels = ~dirt.numChannels; supersawfunc = {|voices| {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15| @@ -31,7 +31,7 @@ ~dirt.soundLibrary.addSynth(\supersaw, (playInside: { |e| ( - instrument: "supersaw" ++ clip(~unison.value ? 5, 1, 10), + instrument: "supersaw" ++ clip(~unison.value ? 3, 1, 10), out: ~out, freq: ~freq, speed: ~speed, @@ -44,17 +44,94 @@ }) ); + superpulsefunc = {|voices| + {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15, z1=0.5, z2=0, z3=0.65, cycle, cps| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound; + var panspread = spread; + var freqspread = detune; + var width = z1; + var modspeed = z2; + var moddepth = z3; + var phaseoffset = (((cycle / cps) * modspeed) % 1); + var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; + width = clip(mod + width,0.01, 0.99); + + if (voices < 2) { + panspread = 0; + }; + sound = Splay.arFill(voices, {|i| + LFPulse.ar( + basefreq * pow(2, StrudelUtils.getUnisonDetune(voices, freqspread, i) / 12), + iphase: TRand.kr(0, 1, Impulse.kr(0)), + // width: width, + width:width; + ) + },spread: panspread, level: 1, center: 0); + sound = sound * 1.2; + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + } + }; + + + (2..10).do{|voices| + var name = "superpulse" ++ voices; + SynthDef.new(name, superpulsefunc.value(voices)).add; + }; + + ~dirt.soundLibrary.addSynth(\superpulse, + (playInside: { |e| + ( + instrument: "superpulse" ++ clip(~unison.value ? 5, 1, 10), + out: ~out, + freq: ~freq, + speed: ~speed, + accelerate: ~accelerate, + amp: ~amp, + cycle: ~cycle, + cps: ~cps, + z1: ~z1 ? ~n ? 0.5, + z2: ~z2, + z3: ~z3 ? 0.65, + detune: ~detune.value ? ~n.value ? 0.12, + spread: ~spread ? 1, + group: ~synthGroup + ).play + }) + ); + sawfunc = { - {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound = SawDPW.ar(freq: basefreq); - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - } + {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var sound = SawDPW.ar(freq: basefreq); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + } }; - SynthDef.new(\supersaw1, sawfunc.value()).add; + SynthDef(\supersaw1, sawfunc.value()).add; SynthDef(\sawtooth, sawfunc.value()).add; + pulsefunc = { + {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| + var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); + var width = z1; + var modspeed = z2; + var moddepth = z3; + var phaseoffset = (((cycle / cps) * modspeed) % 1) * 4; + + var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; + var sound = Pulse.ar(basefreq, width: clip(mod + width,0.01, 0.99)); + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + } + }; + + SynthDef(\superpulse1, pulsefunc.value()).add; + SynthDef(\pulse, pulsefunc.value()).add; + + + + SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = SinOsc.ar(basefreq); @@ -114,8 +191,7 @@ SynthDef("strudel_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | var signal = In.ar(out, numChannels); cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - resonance = StrudelUtils.calculateResonance(resonance); - signal = IIRFilter.ar(signal, cutoff, resonance); + signal = SVF.ar(signal, cutoff: cutoff, res: resonance); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; @@ -140,7 +216,6 @@ SynthDef("strudel_hpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime| var signal = In.ar(out, numChannels); cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - resonance = StrudelUtils.calculateResonance(resonance); signal = RHPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), resonance); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; @@ -166,7 +241,6 @@ SynthDef("strudel_bpf" ++ numChannels, { |out, cutoff=440, resonance=0, attack, hold, decay, envamt=0, anchor=0, release, holdtime| var signal = In.ar(out, numChannels); cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - resonance = StrudelUtils.calculateResonance(resonance); signal = BPF.ar(signal, cutoff, 1/resonance) * max(resonance, 1.0); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 7547bc2c..487a61bb 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -280,7 +280,6 @@ live coding them requires that you have your SuperDirt instance in an environmen SynthDef("dirt_lpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime | var signal = In.ar(out, numChannels); cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - resonance = StrudelUtils.calculateResonance(resonance); signal = IIRFilter.ar(signal, cutoff, resonance); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; From 266b616ecd1635d8f6e4564fa9c40a94655786cd Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 8 Sep 2024 00:32:35 -0400 Subject: [PATCH 25/34] fix: gain staging --- classes/DirtEvent.sc | 1 - classes/DirtEventTypes.sc | 2 +- classes/DirtOrbit.sc | 2 +- classes/StrudelUtils.sc | 4 ++++ classes/SuperDirtUGens.sc | 25 ----------------------- library/strudel-synths.scd | 38 ++++++++++++++--------------------- synths/core-synths-global.scd | 5 ++++- synths/core-synths.scd | 6 +++--- 8 files changed, 28 insertions(+), 55 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 366067b4..1dad0f30 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -192,7 +192,6 @@ DirtEvent { *[ in: orbit.synthBus.index, // read from synth bus, which is reused out: orbit.dryBus.index, // write to orbital dry bus - amp: ~amp, gain: ~gain, overgain: ~overgain, sample: ~hash, // required for the cutgroup mechanism diff --git a/classes/DirtEventTypes.sc b/classes/DirtEventTypes.sc index acbb0a48..22f0bc89 100644 --- a/classes/DirtEventTypes.sc +++ b/classes/DirtEventTypes.sc @@ -117,7 +117,7 @@ DirtEventTypes { schedmidi.value({ midiout.polyTouch(chan, note, val) }) } { // match dirt_gate SynthDef amplitude scaling - ~amp = ~amp.value * pow(~gain.min(2) + ~overgain, 4); + ~amp = ~amp.value * StrudelUtils.gainCurve(~gain + ~overgain, 4); sustain = ~sustain = ~sustain.value; if(~uid.notNil and: { midiout.notNil }) { diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 72a8c538..580cd42e 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -190,7 +190,7 @@ DirtOrbit { ~dry = 0.0; ~lock = 0; // if set to 1, syncs delay times with cps - ~amp = 0.6; + ~amp = 0.3; ~fadeTime = 0.001; diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index fe5bc4c2..368a7225 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -35,6 +35,10 @@ StrudelUtils { *sampleGain { ^1.7; } + *gainCurve {|gain=1| + // ^gain + ^pow(gain, 2) + } } diff --git a/classes/SuperDirtUGens.sc b/classes/SuperDirtUGens.sc index 4fb24751..c6c0e6c6 100644 --- a/classes/SuperDirtUGens.sc +++ b/classes/SuperDirtUGens.sc @@ -193,29 +193,4 @@ DirtPause { } } -DirtEnvelope { - *adsr { - |attack, decay, holdtime, hold, release, envmin = 0, envmax = 1, curve = -4| - if (hold.isNil) { - if (decay.isNil) { - hold = envmax; - } { - hold = envmin; - }; - } { - hold = envmin + ((envmax - envmin) * hold).clip(envmin, envmax); - }; - - ^Env.adsr( - attackTime: attack, - decayTime:decay, - sustainLevel: hold, - releaseTime: release, - peakLevel: envmax, - curve: curve, - bias: envmin - ) - } -} - diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 3540c079..03cd3491 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,6 +1,7 @@ ( - var sawfunc, supersawfunc, pulsefunc, superpulsefunc; + var sawfunc, supersawfunc, pulsefunc, superpulsefunc, calculateCutoff; var numChannels = ~dirt.numChannels; + supersawfunc = {|voices| {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); @@ -55,7 +56,7 @@ var moddepth = z3; var phaseoffset = (((cycle / cps) * modspeed) % 1); var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; - width = clip(mod + width,0.01, 0.99); + width = clip(mod + width,0.01, 0.99); if (voices < 2) { panspread = 0; @@ -64,11 +65,10 @@ LFPulse.ar( basefreq * pow(2, StrudelUtils.getUnisonDetune(voices, freqspread, i) / 12), iphase: TRand.kr(0, 1, Impulse.kr(0)), - // width: width, width:width; ) },spread: panspread, level: 1, center: 0); - sound = sound * 1.2; + sound = HPF.ar(sound, 20); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } }; @@ -113,14 +113,16 @@ pulsefunc = { {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| + var sound; var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var width = z1; var modspeed = z2; var moddepth = z3; var phaseoffset = (((cycle / cps) * modspeed) % 1) * 4; - var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; - var sound = Pulse.ar(basefreq, width: clip(mod + width,0.01, 0.99)); + + width = clip(mod + width,0.01,0.99); + sound = Pulse.ar(basefreq, width: width) * 0.8; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } @@ -138,19 +140,6 @@ Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; - SynthDef(\pulse, {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| - var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var width = z1; - var modspeed = z2; - var moddepth = z3; - var phaseoffset = (((cycle / cps) * modspeed) % 1) * 4; - - var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; - var sound = Pulse.ar(basefreq, width: clip(mod + width,0.01, 0.99)); - - Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - }).add; - SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = LFTri.ar(basefreq); @@ -268,8 +257,10 @@ var signal = In.ar(out, numChannels), amp = 1; shape = exp(shape) - 1; + // shape = min(shape, 1.0 - 4e-10); // avoid division by zero postgain = clip(postgain, 0.001, 1); + postgain = StrudelUtils.gainCurve(postgain); signal = ((1 + shape) * signal / (1 + (shape * abs(signal)))) * postgain; ReplaceOut.ar(out, signal * amp) @@ -359,11 +350,11 @@ ]) }, { ~compressor.notNil }); - SynthDef("strudel_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, curve | + SynthDef("strudel_envelope" ++ numChannels, { |out, attack, decay, hold, holdtime = 0, release, amp=0.3, curve | var signal = In.ar(out, numChannels); var volenv = EnvGen.ar( Env.adsr( - attackTime: attack, + attackTime: attack.max(0.001), decayTime: decay, releaseTime: release, sustainLevel: hold, @@ -372,7 +363,7 @@ ), gate: Trig.ar(1, holdtime) ); - signal = signal * volenv; + signal = signal * volenv * amp; ReplaceOut.ar(out, signal); }, [\ir, \ir, \ir, \ir, \ir]).add; @@ -384,13 +375,14 @@ decay: ~decay, hold: { ~hold.value ? ~decay.isNil }, holdtime: ~sustain, + amp: ~amp, release: ~release, curve: {~curve.value ? -2}, out: ~out ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['sound','supersaw','dirt_gate','lpf','bpf','hpf','shape','crush','coarse','phaser','compressor','distort','envelope','postgain']); + ~dirt.orderModules(['sound','supersaw','superpulse','dirt_gate','lpf','bpf','hpf','shape','crush','coarse','phaser','compressor','distort','envelope','postgain']); ) diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index bc32075c..062020dd 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -31,11 +31,13 @@ CORE SYNTHDEFS FOR DIRT var post = if(SuperDirt.postBadValues) { 2 } { 0 }; signal = Select.ar(CheckBadValues.ar(signal, post: post) > 0, [signal, DC.ar(0)]); + //remove any low frequency artifacts that can slam the limiter + signal = HPF.ar(signal, 16); signal = Select.ar(limitertype, [ signal, - Limiter.ar(signal), + Limiter.ar(signal, 1.0, 0.05), softclip(signal * 0.5) * 2 ] ); @@ -43,6 +45,7 @@ CORE SYNTHDEFS FOR DIRT DirtPause.ar(signal, graceTime:4); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); + Out.ar(outBus, signal) }, [\ir, \ir, \kr, \kr, \kr]).add; diff --git a/synths/core-synths.scd b/synths/core-synths.scd index 487a61bb..67bad174 100644 --- a/synths/core-synths.scd +++ b/synths/core-synths.scd @@ -183,7 +183,7 @@ live coding them requires that you have your SuperDirt instance in an environmen // the monitor does the mixing and zeroing of the busses for each sample grain // so that they can all play in one bus - SynthDef("dirt_gate" ++ numChannels, { |out, in, totalDuration = 0, fadeInTime = 0.001, fadeTime = 0.001, amp = 1, gain = 1, overgain = 0| + SynthDef("dirt_gate" ++ numChannels, { |out, in, totalDuration = 0, fadeInTime = 0.001, fadeTime = 0.001, gain = 1, overgain = 0| var signal = In.ar(in, numChannels); // doneAction: 14: free surrounding group and all nodes var holdtime = totalDuration - (fadeInTime + fadeTime); @@ -191,8 +191,8 @@ live coding them requires that you have your SuperDirt instance in an environmen var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, holdtime, fadeTime], \sin), doneAction: 14); // var env = EnvGen.ar(Env([0, 1, 1, 0], [fadeInTime, sustain + release, fadeTime], \sin), doneAction: 14); - amp = amp * (gain + overgain); - signal = signal * env * amp * DirtGateCutGroup.ar(fadeTime, doneAction: 14); + gain = StrudelUtils.gainCurve(gain + overgain); + signal = signal * env * gain * DirtGateCutGroup.ar(fadeTime, doneAction: 14); // this takes the signal and offsets it so it matches precisely onto the sample // as scheduled within one block (a synth is always started on the block bondary) OffsetOut.ar(out, signal); From 1becbcc7287786c5b5a2be096f64052932c574c1 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 8 Sep 2024 18:23:09 -0400 Subject: [PATCH 26/34] add non sc3 feedback delay with filtering --- classes/DirtOrbit.sc | 8 +++--- classes/StrudelUtils.sc | 5 +++- library/strudel-synths.scd | 24 ++++++++---------- synths/core-synths-global.scd | 46 +++++++---------------------------- 4 files changed, 27 insertions(+), 56 deletions(-) diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 580cd42e..b596162f 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -163,6 +163,7 @@ DirtOrbit { makeDefaultParentEvent { defaultParentEvent = Event.make { + ~cps = 1.0; ~offset = 0.0; ~begin = 0.0; @@ -174,10 +175,6 @@ DirtOrbit { ~cut = 0.0; ~unit = \r; ~n = nil; - // ~release = 0.001; - // ~totalDuration = #{~sustain.value + ~release.value}; - // ~sustain = #{~sustain.value + ~release.value}; - // ~n = \none; // sample number or note ~octave = 0; ~midinote = #{ (~note ? ~n ? StrudelUtils.baseNote()) + (~octave * 12) }; ~freq = #{ ~midinote.value.midicps }; @@ -192,6 +189,9 @@ DirtOrbit { ~amp = 0.3; ~fadeTime = 0.001; + ~delaytime = 0.1875; + ~delayfeedback = 0.15; + ~lock = 1; // values from the dirt bus diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index 368a7225..0907db2a 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -5,7 +5,10 @@ StrudelUtils { ^result; } *getUnisonDetune { | unison, detune, voiceIndex | - var amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); + var amount = 0; + if (unison > 1){ + amount = StrudelUtils.lerp(detune * -0.5, detune * 0.5, voiceIndex / (unison - 1)); + }; ^amount; } *calculateCutoff {|cutoff=440, anchor=0, envamt=0, hold=0, holdtime, attack, decay, release, cutmin=20, cutmax=20000| diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 03cd3491..54581e08 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -1,7 +1,7 @@ ( var sawfunc, supersawfunc, pulsefunc, superpulsefunc, calculateCutoff; var numChannels = ~dirt.numChannels; - + supersawfunc = {|voices| {|out = 0, rate=1, decay=0, sustain=1, pan= 0, accelerate=0, freq =130.8, speed=1, spread = 0.5, detune = 0.15| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); @@ -24,7 +24,7 @@ } }; - (2..10).do{|voices| + (1..10).do{|voices| var name = "supersaw" ++ voices; SynthDef.new(name, supersawfunc.value(voices)).add; }; @@ -69,12 +69,13 @@ ) },spread: panspread, level: 1, center: 0); sound = HPF.ar(sound, 20); + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } }; - (2..10).do{|voices| + (1..10).do{|voices| var name = "superpulse" ++ voices; SynthDef.new(name, superpulsefunc.value(voices)).add; }; @@ -108,11 +109,11 @@ } }; - SynthDef(\supersaw1, sawfunc.value()).add; SynthDef(\sawtooth, sawfunc.value()).add; - pulsefunc = { - {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| + + + SynthDef(\pulse, {|out, sustain=1, pan, accelerate, freq=130.8, speed=1, z1=0.5, z2=0, z3=0.65, cycle, cps| var sound; var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var width = z1; @@ -120,16 +121,11 @@ var moddepth = z3; var phaseoffset = (((cycle / cps) * modspeed) % 1) * 4; var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; - width = clip(mod + width,0.01,0.99); sound = Pulse.ar(basefreq, width: width) * 0.8; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - } - }; - - SynthDef(\superpulse1, pulsefunc.value()).add; - SynthDef(\pulse, pulsefunc.value()).add; + }).add; @@ -163,7 +159,7 @@ //EFFECTS SynthDef("gain" ++ numChannels, { |out, gain=1.0 | - var signal = In.ar(out, numChannels) * gain; + var signal = In.ar(out, numChannels) * StrudelUtils.gainCurve(gain); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; @@ -205,7 +201,7 @@ SynthDef("strudel_hpf" ++ numChannels, { |out, cutoff = 440, resonance = 0, attack, hold, decay, envamt = 0, anchor = 0, release, holdtime| var signal = In.ar(out, numChannels); cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - signal = RHPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), resonance); + signal = RHPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), 1 - resonance); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index 062020dd..71887a2b 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -77,54 +77,26 @@ CORE SYNTHDEFS FOR DIRT - if(\SwitchDelay.asClass.notNil) { - - SynthDef("dirt_delay" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, delaySend = 1, delayAmp = 1, lock = 0, cps = 1| + SynthDef("dirt_delay" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, delaySend = 1, delayAmp = 1, lock = 1, cps = 1| var signal; var input = In.ar(dryBus, numChannels); var maxDelayTime = 4; - - input = input * delaySend.lag(LFNoise1.kr(1).range(0.01, 0.02)); // regulate input - - delayfeedback = delayfeedback.max(0); delaytime = delaytime * if(lock, reciprocal(cps), 1); - delaytime = delaytime.clip(0, maxDelayTime); // just to be sure - // from sc3-plugins - signal = \SwitchDelay.asClass.ar(input, 1, 1, delaytime, delayfeedback, maxDelayTime); - + // delaytime = delaytime / cps; + signal = input + (LocalIn.ar(2) * delayfeedback); + signal = DelayC.ar(LPF.ar(signal, 10000), maxDelayTime, delaytime ); + LocalOut.ar(signal); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); - signal = signal * delayAmp.lag(0.01); - - DirtPause.ar(signal, graceTime:4); - - Out.ar(effectBus, signal); + signal = signal * StrudelUtils.gainCurve(delayAmp.lag(0.01)); + + signal = Limiter.ar(signal, 0.5, 0.001); - }, [\ir, \ir]).add; - } { - "\n\n ---- SC3-Plugins not found. This is not a problem." - "Note that we are using a comb delay, which may not sound the same as SwitchDelay from the plugins".postln; - - SynthDef("dirt_delay" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, delayAmp = 1, lock = 0, cps = 1| - var signal = In.ar(dryBus, numChannels); - var maxDelayTime = 4; - var decayTime; - - delayfeedback = delayfeedback.clip(0, 0.99); - delaytime = delaytime * if(lock, reciprocal(cps), 1); - delaytime = delaytime.clip(0, maxDelayTime); // just to be sure - decayTime = log2(-60.dbamp) / log2(delayfeedback) * delaytime; - decayTime = decayTime.clip(0, 20); - - signal = CombL.ar(signal, maxDelayTime, delaytime.lag(1), decayTime); - - signal = LeakDC.ar(signal) * delayAmp.lag(0.01) * EnvGen.kr(Env.asr, gate, doneAction:2); DirtPause.ar(signal, graceTime:4); Out.ar(effectBus, signal); - }, [\ir, \ir]).add; - }; + }, [\ir, \ir]).add; // thanks to Jost Muxfeld and James McCartney // note that "size" is not room size, just the feed level into the room From a47e9ffa11ebcc800d71d3f441879aef00fd56a4 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sun, 8 Sep 2024 23:02:47 -0400 Subject: [PATCH 27/34] feat: shimmer delay --- classes/DirtEvent.sc | 1 + classes/DirtOrbit.sc | 1 + library/strudel-synths.scd | 1 + synths/core-synths-global.scd | 23 ++++++++++++++++------- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/classes/DirtEvent.sc b/classes/DirtEvent.sc index 1dad0f30..1f10015b 100644 --- a/classes/DirtEvent.sc +++ b/classes/DirtEvent.sc @@ -160,6 +160,7 @@ DirtEvent { ~channel !? { ~pan = ~pan.value + (~channel.value / ~numChannels) }; ~pan = ~pan * 2 - 1; // convert unipolar (0..1) range into bipolar one (-1...1) ~delayAmp = ~delay ? 0.0; // for clarity + ~z1 = ~z1 ? ~n; ~latency = ~latency + ~lag.value + (~offset.value * ~speed.value.abs); } diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index b596162f..c506c246 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -58,6 +58,7 @@ DirtOrbit { initDefaultGlobalEffects { this.globalEffects = [ // all global effects sleep when the input is quiet for long enough and no parameters are set. + GlobalDirtEffect(\dirt_shimmer, [\delaytime, \delayfeedback, \delaySend, \shimmer, \cps]), GlobalDirtEffect(\dirt_delay, [\delaytime, \delayfeedback, \delaySend, \delayAmp, \lock, \cps]), GlobalDirtEffect(\dirt_reverb, [\size, \room, \dry]), GlobalDirtEffect(\dirt_leslie, [\leslie, \lrate, \lsize]), diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 54581e08..8c2f940e 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -319,6 +319,7 @@ ]) }, { ~phaserrate.notNil }); + SynthDef("strudel_compressor" ++ numChannels, { |out, threshold = 0, ratio = 0.25, knee = 8, attack = 0.1, release = 0.1| var signal = In.ar(out, numChannels), amp = 1; threshold = clip(threshold, 0.01, 100); diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index 71887a2b..c0a6cf26 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -74,6 +74,21 @@ CORE SYNTHDEFS FOR DIRT dryBus and effectBus have \ir as rates (they shouldn't change at runtime) */ + SynthDef("dirt_shimmer" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, shimmer = 0, lock = 1, cps = 1| + var signal; + var input = In.ar(dryBus, numChannels); + var maxDelayTime = 4; + delaytime = delaytime * if(lock, reciprocal(cps), 1); + signal = input + (LocalIn.ar(2) * delayfeedback); + signal = PitchShift.ar(signal, windowSize: 0.375 * 2, pitchRatio: 2, timeDispersion: 0.5); + signal = DelayC.ar(LPF.ar(signal, 10000), maxDelayTime, delaytime ); + LocalOut.ar(signal); + signal = Limiter.ar(signal, 0.5, 0.001); + signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); + signal = signal * StrudelUtils.gainCurve(shimmer.lag(0.01)); + DirtPause.ar(signal, graceTime:4); + Out.ar(effectBus, signal); + }, [\ir, \ir]).add; @@ -82,20 +97,14 @@ CORE SYNTHDEFS FOR DIRT var input = In.ar(dryBus, numChannels); var maxDelayTime = 4; delaytime = delaytime * if(lock, reciprocal(cps), 1); - // delaytime = delaytime / cps; signal = input + (LocalIn.ar(2) * delayfeedback); signal = DelayC.ar(LPF.ar(signal, 10000), maxDelayTime, delaytime ); LocalOut.ar(signal); + signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); signal = signal * StrudelUtils.gainCurve(delayAmp.lag(0.01)); - - signal = Limiter.ar(signal, 0.5, 0.001); - - DirtPause.ar(signal, graceTime:4); - Out.ar(effectBus, signal); - }, [\ir, \ir]).add; // thanks to Jost Muxfeld and James McCartney From c96ef2aa27f50ecaf22a1c9bfbc799e8117a0645 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 9 Sep 2024 00:39:11 -0400 Subject: [PATCH 28/34] feat: juno chorus --- library/strudel-synths.scd | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 8c2f940e..35fa94bf 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -247,6 +247,38 @@ ]) }, { ~bandf.notNil }); + //emulation of juno 60 chorus + SynthDef("strudel_chorus" ++ numChannels, { |out, mix, depth, speed| + var input = In.ar(out, numChannels); + var l; + var r; + var signal; + var d = depth * 0.01; + var minD = 0.00166; + var mod = LFTri.kr(speed).range(-1, 1) * d; + var rmod = mod * -1; + mix = (mix * 2) - 1; + l = DelayC.ar(input, maxDelayTime: 1, delaytime: minD + d + mod ); + r = DelayC.ar(input, maxDelayTime: 1, delaytime: minD + d + rmod ); + signal = Splay.ar([l, r],spread: 1, level: 1, center: 0); + signal = XFade2.ar(input, signal, mix); + + signal = DirtPan.ar(signal, ~dirt.numChannels, 0); + ReplaceOut.ar(out, signal); + }, [\ir, \kr, \kr]).add; + + ~dirt.addModule('chorus', + { |dirtEvent| + dirtEvent.sendSynth("strudel_chorus" ++ ~numChannels, + [ + mix: ~chorus, + depth: {~chorusdepth.value ? 0.1845}, + speed: {~chorusspeed.value ? 0.863}, + out: ~out + ]) + + }, { ~chorus.notNil }); + SynthDef("strudel_distort" ++ numChannels, { |out, shape = 0, postgain = 1| @@ -379,7 +411,7 @@ ]) }, { ~attack.notNil or: { ~release.notNil } or: { ~decay.notNil } or: { ~hold.notNil }}); - ~dirt.orderModules(['sound','supersaw','superpulse','dirt_gate','lpf','bpf','hpf','shape','crush','coarse','phaser','compressor','distort','envelope','postgain']); + ~dirt.orderModules(['sound','supersaw','superpulse','dirt_gate','lpf','bpf','hpf','shape','crush','coarse','phaser','compressor','chorus','distort','envelope','postgain']); ) From bcf605e2dca8fe5c41068481054caff55b7db7ad Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Mon, 9 Sep 2024 18:21:25 -0400 Subject: [PATCH 29/34] fix chorus stereo imaging --- library/strudel-synths.scd | 14 ++++++++------ synths/core-synths-global.scd | 5 ++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 35fa94bf..0c4d9800 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -250,20 +250,22 @@ //emulation of juno 60 chorus SynthDef("strudel_chorus" ++ numChannels, { |out, mix, depth, speed| var input = In.ar(out, numChannels); - var l; - var r; + var l = input[0]; + var r = input[1] ? l; var signal; var d = depth * 0.01; var minD = 0.00166; var mod = LFTri.kr(speed).range(-1, 1) * d; var rmod = mod * -1; + mix = (mix * 2) - 1; - l = DelayC.ar(input, maxDelayTime: 1, delaytime: minD + d + mod ); - r = DelayC.ar(input, maxDelayTime: 1, delaytime: minD + d + rmod ); + l = DelayC.ar(l, maxDelayTime: 1, delaytime: minD + d + mod ); + r = DelayC.ar(r, maxDelayTime: 1, delaytime: minD + d + rmod ); + signal = Splay.ar([l, r],spread: 1, level: 1, center: 0); - signal = XFade2.ar(input, signal, mix); + signal = LPF.ar(signal, 18000); - signal = DirtPan.ar(signal, ~dirt.numChannels, 0); + signal = XFade2.ar(input, signal, mix); ReplaceOut.ar(out, signal); }, [\ir, \kr, \kr]).add; diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index c0a6cf26..900ee50a 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -81,8 +81,11 @@ CORE SYNTHDEFS FOR DIRT delaytime = delaytime * if(lock, reciprocal(cps), 1); signal = input + (LocalIn.ar(2) * delayfeedback); signal = PitchShift.ar(signal, windowSize: 0.375 * 2, pitchRatio: 2, timeDispersion: 0.5); - signal = DelayC.ar(LPF.ar(signal, 10000), maxDelayTime, delaytime ); + signal = LPF.ar(signal, 10000); + signal = HPF.ar(signal, 120); + signal = DelayC.ar(signal, maxDelayTime, delaytime ); LocalOut.ar(signal); + signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); signal = signal * StrudelUtils.gainCurve(shimmer.lag(0.01)); From b1144730d379f326d29d2ab17e8243f64585a3ed Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Wed, 11 Sep 2024 00:13:54 -0400 Subject: [PATCH 30/34] fix reverb and delay send behavior --- synths/core-synths-global.scd | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index 900ee50a..7a941029 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -76,11 +76,12 @@ CORE SYNTHDEFS FOR DIRT */ SynthDef("dirt_shimmer" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, shimmer = 0, lock = 1, cps = 1| var signal; - var input = In.ar(dryBus, numChannels); + var input = In.ar(dryBus, numChannels) * StrudelUtils.gainCurve(shimmer.lag(0.01)); var maxDelayTime = 4; + var delta = 0.375 * 2; delaytime = delaytime * if(lock, reciprocal(cps), 1); signal = input + (LocalIn.ar(2) * delayfeedback); - signal = PitchShift.ar(signal, windowSize: 0.375 * 2, pitchRatio: 2, timeDispersion: 0.5); + signal = PitchShift.ar(signal, windowSize: delta, pitchRatio: 2, timeDispersion: delta / 2); signal = LPF.ar(signal, 10000); signal = HPF.ar(signal, 120); signal = DelayC.ar(signal, maxDelayTime, delaytime ); @@ -88,7 +89,7 @@ CORE SYNTHDEFS FOR DIRT signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); - signal = signal * StrudelUtils.gainCurve(shimmer.lag(0.01)); + // signal = signal * StrudelUtils.gainCurve(shimmer.lag(0.01)); DirtPause.ar(signal, graceTime:4); Out.ar(effectBus, signal); }, [\ir, \ir]).add; @@ -97,7 +98,7 @@ CORE SYNTHDEFS FOR DIRT SynthDef("dirt_delay" ++ numChannels, { |dryBus, effectBus, gate = 1, delaytime, delayfeedback, delaySend = 1, delayAmp = 1, lock = 1, cps = 1| var signal; - var input = In.ar(dryBus, numChannels); + var input = In.ar(dryBus, numChannels) * StrudelUtils.gainCurve(delayAmp.lag(0.01)); var maxDelayTime = 4; delaytime = delaytime * if(lock, reciprocal(cps), 1); signal = input + (LocalIn.ar(2) * delayfeedback); @@ -105,7 +106,7 @@ CORE SYNTHDEFS FOR DIRT LocalOut.ar(signal); signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); - signal = signal * StrudelUtils.gainCurve(delayAmp.lag(0.01)); + // signal = signal * StrudelUtils.gainCurve(delayAmp.lag(0.01)); DirtPause.ar(signal, graceTime:4); Out.ar(effectBus, signal); }, [\ir, \ir]).add; @@ -113,7 +114,7 @@ CORE SYNTHDEFS FOR DIRT // thanks to Jost Muxfeld and James McCartney // note that "size" is not room size, just the feed level into the room - SynthDef("dirt_reverb" ++ numChannels, { |dryBus, effectBus, gate = 1, room = 0, size = 0.1, dry = 0| + SynthDef("dirt_reverb" ++ numChannels, { |dryBus, effectBus, gate = 1, room = 0, size = 0.1| var in, snd, loop, depth; in = In.ar(dryBus, numChannels).asArray.sum; @@ -123,7 +124,7 @@ CORE SYNTHDEFS FOR DIRT 4.do { in = AllpassN.ar(in, 0.03, { Rand(0.005, 0.02) }.dup(numChannels), 1) }; depth = size.lag(0.02).linexp(0, 1, 0.01, 0.98); // change depth between 0.1 and 0.98 - loop = LocalIn.ar(numChannels) * { depth + Rand(0, 0.05) }.dup(numChannels); + loop = in + LocalIn.ar(numChannels) * { depth + Rand(0, 0.05) }.dup(numChannels); loop = OnePole.ar(loop, 0.5); // 0-1 loop = AllpassN.ar(loop, 0.05, { Rand(0.01, 0.05) }.dup(numChannels), 2); @@ -131,13 +132,13 @@ CORE SYNTHDEFS FOR DIRT loop = DelayN.ar(loop, 0.3, [0.19, 0.26] + { Rand(-0.003, 0.003) }.dup(2)); loop = AllpassN.ar(loop, 0.05, { Rand(0.03, 0.15) }.dup(numChannels), 2); - loop = loop + in; + // loop = loop + in; loop = LeakDC.ar(loop); LocalOut.ar(loop); snd = loop; - snd = snd * (1 - dry).lag(LFNoise1.kr(1).range(0.01, 0.02)); + snd = snd * (1).lag(LFNoise1.kr(1).range(0.01, 0.02)); DirtPause.ar(snd, graceTime:4); From 48d2bad9a0d12dc7cfffb6c70007ead75d8a7862 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Fri, 13 Sep 2024 01:16:27 -0400 Subject: [PATCH 31/34] fix volume normalization --- classes/DirtOrbit.sc | 2 +- classes/StrudelUtils.sc | 5 ++++- classes/SuperDirt.sc | 5 +++++ library/default-synths-extra.scd | 18 ++++++++++++++++++ library/strudel-synths.scd | 12 ++++++++++-- synths/core-synths-global.scd | 4 +--- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index c506c246..0ff59f59 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -188,7 +188,7 @@ DirtOrbit { ~dry = 0.0; ~lock = 0; // if set to 1, syncs delay times with cps - ~amp = 0.3; + ~amp = 1; ~fadeTime = 0.001; ~delaytime = 0.1875; ~delayfeedback = 0.15; diff --git a/classes/StrudelUtils.sc b/classes/StrudelUtils.sc index 0907db2a..97eecff5 100644 --- a/classes/StrudelUtils.sc +++ b/classes/StrudelUtils.sc @@ -36,7 +36,10 @@ StrudelUtils { } //makeup gain for sample buffer *sampleGain { - ^1.7; + ^1; + } + *synthGain { + ^0.27; } *gainCurve {|gain=1| // ^gain diff --git a/classes/SuperDirt.sc b/classes/SuperDirt.sc index 14a11fbd..15bf6592 100644 --- a/classes/SuperDirt.sc +++ b/classes/SuperDirt.sc @@ -33,6 +33,7 @@ SuperDirt { var <>controlBusses; var receiveAction, <>warnOutOfOrbit = true, <>maxLatency = 42; @@ -53,10 +54,14 @@ SuperDirt { init { soundLibrary = DirtSoundLibrary(server, numChannels); + outputvolume = server.volume; + outputvolume.setVolumeRange(-90, 0); modules = []; this.loadSynthDefs; this.initVowels(\counterTenor); this.initRoutingBusses; + + group = server.nextPermNodeID; flotsam = IdentityDictionary.new; } diff --git a/library/default-synths-extra.scd b/library/default-synths-extra.scd index a7ecc443..c987dad9 100644 --- a/library/default-synths-extra.scd +++ b/library/default-synths-extra.scd @@ -101,6 +101,7 @@ 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 ); @@ -116,6 +117,7 @@ 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)); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); @@ -179,6 +181,7 @@ SinOsc.ar(basefreq/64*rate, 0).range(lfof1,lfof2), resonance*4); sound = sound.tanh * 2; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); @@ -222,6 +225,7 @@ 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; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); @@ -241,6 +245,7 @@ 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)); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(0.5*sound, ~dirt.numChannels, pan, env)); }).add ); @@ -263,6 +268,7 @@ 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; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); @@ -287,6 +293,7 @@ 2*voice-1); sound = HPF.ar(BMoog.ar(sound, ffreq, resonance, 3), 20); sound = clip(sound, -1,1) * 0.3; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); @@ -342,6 +349,7 @@ SynthDef(\superhammond, {|out, sustain=1, decay=0, pan, freq, vibrato=0.5, vrate 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)); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add ); @@ -393,6 +401,7 @@ SynthDef(\superhoover, {|out, sustain=1, decay=0, pan, freq, accelerate=0, slide 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); + mix = mix * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(1.4*mix, ~dirt.numChannels, pan, env)); }).add ); @@ -411,6 +420,7 @@ SynthDef(\superzow, {|out, sustain=1, pan, accelerate, freq, decay=0, slide=1, d 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); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound/2, ~dirt.numChannels, pan, env)); }).add ); @@ -424,6 +434,7 @@ SynthDef(\superstatic, {|out, sustain=1, pan, freq, accelerate=0, speed=1 | freq = freq * DirtFreqScale.kr(speed, accelerate, sustain); sound = Dust.ar(freq*40) > 0.5; sound = Pulse.ar(freq*sound*4,0.5,0.5); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)) }).add ); @@ -447,6 +458,8 @@ SynthDef(\supergrind, {|out, pan, freq, sustain, accelerate, detune=0, voice=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; + loop = loop * StrudelUtils.synthGain; + Out.ar(out, DirtPan.ar(0.3*loop, ~dirt.numChannels, pan, env)); }).add; ); @@ -469,6 +482,7 @@ SynthDef(\superprimes, {|out, pan, freq, sustain, accelerate, rate=1, detune=0, * 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)); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); @@ -490,6 +504,7 @@ SynthDef(\superwavemechanics, {|out, pan, freq, sustain, accelerate, detune=0, v 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; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound.flat, ~dirt.numChannels, pan, env)); }).add; ); @@ -505,6 +520,7 @@ SynthDef(\supertron, {|out, pan, freq, sustain, voice, detune, accelerate, speed 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); + sound = sound * StrudelUtils.synthGain; LocalOut.ar(sound); Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, aenv)) }).add; @@ -523,6 +539,7 @@ SynthDef(\superreese, {|out, pan, freq, sustain, accelerate, detune=0, voice=0, 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); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); @@ -636,6 +653,7 @@ SynthDef(\superfm, { var sound = FM7.ar(ctls, presets[5]) * amps; sound = Mix.ar(sound) * (-15.dbamp); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan, env)); }).add; ); diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 0c4d9800..a7261512 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -18,7 +18,8 @@ iphase: TRand.kr(-1, 1, Impulse.kr(0)) ) },spread: panspread, level: 1, center: 0); - sound = sound * 1.2; + sound = sound * 1.24; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } @@ -69,6 +70,7 @@ ) },spread: panspread, level: 1, center: 0); sound = HPF.ar(sound, 20); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } @@ -104,7 +106,7 @@ sawfunc = { {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); - var sound = SawDPW.ar(freq: basefreq); + var sound = SawDPW.ar(freq: basefreq) * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); } }; @@ -123,6 +125,7 @@ var mod = LFTri.ar(modspeed, iphase: phaseoffset).range(-0.5,0.5) * moddepth; width = clip(mod + width,0.01,0.99); sound = Pulse.ar(basefreq, width: width) * 0.8; + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; @@ -133,25 +136,30 @@ SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = SinOsc.ar(basefreq); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = LFTri.ar(basefreq); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; SynthDef(\white, {|out, pan| var sound = WhiteNoise.ar(mul:0.5); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; SynthDef(\brown, {|out, pan| var sound = BrownNoise.ar(mul:0.5); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; SynthDef(\pink, {|out, pan| var sound = PinkNoise.ar(mul:0.5); + sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index 7a941029..a70af163 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -37,7 +37,7 @@ CORE SYNTHDEFS FOR DIRT signal = Select.ar(limitertype, [ signal, - Limiter.ar(signal, 1.0, 0.05), + Limiter.ar(signal, 1.0, 0.01), softclip(signal * 0.5) * 2 ] ); @@ -89,7 +89,6 @@ CORE SYNTHDEFS FOR DIRT signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); - // signal = signal * StrudelUtils.gainCurve(shimmer.lag(0.01)); DirtPause.ar(signal, graceTime:4); Out.ar(effectBus, signal); }, [\ir, \ir]).add; @@ -106,7 +105,6 @@ CORE SYNTHDEFS FOR DIRT LocalOut.ar(signal); signal = Limiter.ar(signal, 0.5, 0.001); signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2); - // signal = signal * StrudelUtils.gainCurve(delayAmp.lag(0.01)); DirtPause.ar(signal, graceTime:4); Out.ar(effectBus, signal); }, [\ir, \ir]).add; From 019c1ba82550da5ef939947b2ded22ec35cad62f Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Tue, 17 Sep 2024 00:57:56 -0400 Subject: [PATCH 32/34] first synthkick --- library/strudel-synths.scd | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index a7261512..29f774d3 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -131,16 +131,16 @@ }).add; + - - SynthDef(\sine, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq=130.8, speed=1| + SynthDef(\sine, {|out, rate=1, sustain=1, pan, accelerate, freq=130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = SinOsc.ar(basefreq); sound = sound * StrudelUtils.synthGain; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); }).add; - SynthDef(\triangle, {|out, rate=1, decay=0, sustain=1, pan, accelerate, freq = 130.8, speed=1| + SynthDef(\triangle, {|out, rate=1, sustain=1, pan, accelerate, freq = 130.8, speed=1| var basefreq = freq * DirtFreqScale.kr(speed, accelerate, sustain); var sound = LFTri.ar(basefreq); sound = sound * StrudelUtils.synthGain; @@ -164,6 +164,32 @@ }).add; + // PERCUSSION + // gabber kick + SynthDef(\sbd2, { |out, pan, freq = 440, z1 = 0, z2 = 0, z3 = 0, z4 = 0| + var sound; + var dec = 0.15 + z1; + var pitchenv = Env.perc(0.001, dec, curve: -3).ar; + var volenv = Env.perc(0.001, dec, curve: 2).ar; + var volratio = clip(z2 + 0.2, 0, 1); + var knockdecay = 0.01 + (z3 * 0.1); + var knockenv = Env.perc(0.001, knockdecay, -4).ar; + var fmosc = SinOsc.ar(freq *3, 0, freq *3) ; + var knock = SinOsc.ar(freq + fmosc)* knockenv; + + volenv = (volenv * volratio) + (1 - volratio); + freq = freq * (pitchenv * clip(48 - (z4 * 48), 1, 60)).midiratio; + sound = Saw.ar(freq); + sound = sound + knock; + sound = (sound * 100).tanh + ((sound.sign - sound) * -8.dbamp); + sound = sound * volenv * 0.3; + + Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); + + // Out.ar(\out.kr(0), sound * \amp.kr(0.1)); + }).add; + + //EFFECTS SynthDef("gain" ++ numChannels, { |out, gain=1.0 | From ad53027ef969009433725ca9fc8ce8bfc20554e7 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 12 Oct 2024 23:42:39 -0400 Subject: [PATCH 33/34] feat: limiter gain, wet gain, dry gain --- classes/DirtOrbit.sc | 6 ++++-- classes/SuperDirt.sc | 2 +- hacks/adding-a-compressor.scd | 2 +- library/strudel-synths.scd | 6 ++---- synths/core-synths-global.scd | 9 ++++----- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/classes/DirtOrbit.sc b/classes/DirtOrbit.sc index 0ff59f59..93a6cc3d 100644 --- a/classes/DirtOrbit.sc +++ b/classes/DirtOrbit.sc @@ -63,7 +63,7 @@ DirtOrbit { GlobalDirtEffect(\dirt_reverb, [\size, \room, \dry]), GlobalDirtEffect(\dirt_leslie, [\leslie, \lrate, \lsize]), GlobalDirtEffect(\dirt_rms, [\rmsReplyRate, \rmsPeakLag]).alwaysRun_(true), - GlobalDirtEffect(\dirt_monitor, [\limitertype]).alwaysRun_(true), + GlobalDirtEffect(\dirt_monitor, [\limitertype, \outgain, \dry, \wet]).alwaysRun_(true), ] } @@ -185,7 +185,8 @@ DirtOrbit { ~lag = 0.0; ~length = 1.0; ~loop = 1.0; - ~dry = 0.0; + ~dry = 1.0; + ~wet = 1.0; ~lock = 0; // if set to 1, syncs delay times with cps ~amp = 1; @@ -193,6 +194,7 @@ DirtOrbit { ~delaytime = 0.1875; ~delayfeedback = 0.15; ~lock = 1; + ~outgain = 1; // output gain that drives the final limiter // values from the dirt bus diff --git a/classes/SuperDirt.sc b/classes/SuperDirt.sc index 15bf6592..eb5d3ceb 100644 --- a/classes/SuperDirt.sc +++ b/classes/SuperDirt.sc @@ -55,7 +55,7 @@ SuperDirt { init { soundLibrary = DirtSoundLibrary(server, numChannels); outputvolume = server.volume; - outputvolume.setVolumeRange(-90, 0); + outputvolume.setVolumeRange(-90, 6); modules = []; this.loadSynthDefs; this.initVowels(\counterTenor); diff --git a/hacks/adding-a-compressor.scd b/hacks/adding-a-compressor.scd index 963ed9c3..b40f699d 100644 --- a/hacks/adding-a-compressor.scd +++ b/hacks/adding-a-compressor.scd @@ -7,7 +7,7 @@ GlobalDirtEffect(\dirt_reverb, [\size, \room, \dry]), GlobalDirtEffect(\dirt_leslie, [\leslie, \lrate, \lsize]), GlobalDirtEffect(\dirt_rms, [\rmsReplyRate, \rmsPeakLag]).alwaysRun_(true), - GlobalDirtEffect(\dirt_monitor, [\limitertype]).alwaysRun_(true), + GlobalDirtEffect(\dirt_monitor, [\limitertype, \outgain]).alwaysRun_(true), ] }; ) diff --git a/library/strudel-synths.scd b/library/strudel-synths.scd index 29f774d3..1ec6e496 100644 --- a/library/strudel-synths.scd +++ b/library/strudel-synths.scd @@ -185,8 +185,6 @@ sound = sound * volenv * 0.3; Out.ar(out, DirtPan.ar(sound, ~dirt.numChannels, pan)); - - // Out.ar(\out.kr(0), sound * \amp.kr(0.1)); }).add; @@ -259,8 +257,8 @@ SynthDef("strudel_bpf" ++ numChannels, { |out, cutoff=440, resonance=0, attack, hold, decay, envamt=0, anchor=0, release, holdtime| var signal = In.ar(out, numChannels); - cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); - signal = BPF.ar(signal, cutoff, 1/resonance) * max(resonance, 1.0); + cutoff = StrudelUtils.calculateCutoff(cutoff,anchor, envamt, hold, holdtime, attack, decay, release, cutmax: SampleRate.ir / 2); + signal = BPF.ar(signal, cutoff.abs.clip(20, SampleRate.ir / 2), resonance.abs.clip(0.05, 1)); ReplaceOut.ar(out, signal) }, [\ir, \kr, \kr]).add; diff --git a/synths/core-synths-global.scd b/synths/core-synths-global.scd index a70af163..762ffe97 100644 --- a/synths/core-synths-global.scd +++ b/synths/core-synths-global.scd @@ -23,16 +23,15 @@ CORE SYNTHDEFS FOR DIRT */ - SynthDef("dirt_monitor" ++ numChannels, { |dryBus, effectBus, outBus, gate = 1, limitertype = 1| - var drySignal = In.ar(dryBus, numChannels); - var wetSignal = In.ar(effectBus, numChannels); + SynthDef("dirt_monitor" ++ numChannels, { |dryBus, effectBus, outBus, gate = 1, limitertype = 1, outgain = 1, dry = 1, wet = 1| + var drySignal = In.ar(dryBus, numChannels) * StrudelUtils.gainCurve(dry); + var wetSignal = In.ar(effectBus, numChannels) * StrudelUtils.gainCurve(wet); //var signal = XFade2.ar(wetSignal, drySignal, dry * 2 - 1); var signal = wetSignal + drySignal; var post = if(SuperDirt.postBadValues) { 2 } { 0 }; - signal = Select.ar(CheckBadValues.ar(signal, post: post) > 0, [signal, DC.ar(0)]); //remove any low frequency artifacts that can slam the limiter - signal = HPF.ar(signal, 16); + signal = HPF.ar(signal, 16) * StrudelUtils.gainCurve(outgain); signal = Select.ar(limitertype, [ From e9ab9d9ce3de1bf0f87b8977286ff919e2dfc8a1 Mon Sep 17 00:00:00 2001 From: "Jade (Rose) Rowland" Date: Sat, 12 Oct 2024 23:55:33 -0400 Subject: [PATCH 34/34] updated readme --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 8b103763..4bd9ceea 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,21 @@ # SuperTweak This is a fork of superdirt that is intended to play well with Strudel.cc +The intention of the fork is to be temporary, as features are planned to be merged back into superdirt over time. Features: +- note scaling is the same as Strudel +- Shimmer Reverb effect ".shimmer(1)" +- new oscillator types: supersaw, superpulse, sawtooth, triangle, pulse +- z parameters AKA oscillator macros z/z1,z2,z3,z4 +- pwm modulation ".s("pulse").z(.5).z2(3).z3(.8)" +- better delay effect with cycle relative timing ".delaytime(3/16)" +- filter envelopes for each filter type +- distort +- FX bus gain behavior is improved to work like a mixing console +- gain modules: ".gain" is pre effect ".postgain" is pre orbit effect +- ".dry" and ".wet" control the relative levels of effect bus so you can get a totally "wet" sound for example with ".room(1).dry(0)" +- relative gain of synths to samples is improved and normalized +- better sounding filters +- improved gaincurve x^2 (as opposed to x^4 in superdirt or x in Strudel ) +- Juno 60 Chorus emulation ".chorus(.5)" SuperCollider implementation of the Dirt sampler, originally designed for the [TidalCycles](https://github.com/tidalcycles/tidal)