diff --git a/Bubo.quark b/Bubo.quark index 70a1e88..c95a545 100644 --- a/Bubo.quark +++ b/Bubo.quark @@ -9,7 +9,7 @@ dependencies: [ "https://github.com/scztt/Singleton.quark", "https://github.com/scztt/Require.quark", - "https://github.com/supercollider-quarks/BatLib", + // "https://github.com/supercollider-quarks/BatLib", "https://github.com/supercollider-quarks/Bjorklund", ], url: "https://raphaelforment.fr", diff --git a/Classes/BuboBoot.sc b/Classes/BuboBoot.sc index 44bac3b..2a979dd 100644 --- a/Classes/BuboBoot.sc +++ b/Classes/BuboBoot.sc @@ -7,25 +7,27 @@ Boot { var ready = "┓ ┳┓┏┏┓ ┏┓┏┓┳┓┏┓ ┳┓┏┓┏┓┳┓┓┏\n" "┃ ┃┃┃┣ ┃ ┃┃┃┃┣ ┣┫┣ ┣┫┃┃┗┫\n" "┗┛┻┗┛┗┛ ┗┛┗┛┻┛┗┛ ┛┗┗┛┛┗┻┛┗┛"; + var p; var c; var m; var s = Server.default; - var clock = LinkClock(130 / 60).latency_(Server.default.latency); - var p; + var clock = LinkClock(130 / 60).latency_(Server.default.latency).permanent_(True); "=-=-=-=-=-=-=-=-=-=-=".postln; banner.postln; "=-=-=-=-=-=-=-=-=-=-=".postln; - s.options.numBuffers = 1024 * 128; // Nombre de buffers disponibles pour stocker des samples - s.options.memSize = 8192 * 64; // Mémoire disponible pour le serveur - s.options.numWireBufs = 2048; // Augmenter ce nombre si "exceeded number of interconnect buffers" - s.options.maxNodes = 1024 * 32; // Changer cette valeur si le son saute avec le message "too many nodes" - s.options.device = "BlackHole 16ch"; // Choix de l'interface audio à utiliser - s.options.numOutputBusChannels = 16; // Indiquer le nombre de sorties de son interface audio - s.options.numInputBusChannels = 16; // Indiquer le nombre d'entrées de son interface audio + s.options.numBuffers = 1024 * 128; // Nombre de buffers disponibles pour stocker des samples + s.options.memSize = 8192 * 64; // Mémoire disponible pour le serveur + s.options.numWireBufs = 2048; // Augmenter ce nombre si "exceeded number of interconnect buffers" + s.options.maxNodes = 1024 * 32; // Changer cette valeur si le son saute avec le message "too many nodes" + s.options.device = "BlackHole 16ch"; // Choix de l'interface audio à utiliser + s.options.numOutputBusChannels = 16; // Indiquer le nombre de sorties de son interface audio + s.options.numInputBusChannels = 16; // Indiquer le nombre d'entrées de son interface audio p = ProxySpace.push(Server.default.boot, clock: clock); + c = clock; Bank.root = path +/+ "samples"; // Chemin vers les samples - Bank.lazyLoading = True; // Lazy loading des samples + Bank.lazyLoading = True; // Lazy loading des samples Server.default.waitForBoot({ - (path +/+ "Synthdefs.scd").load; // Chargement des synthétiseurs - StageLimiter.activate; // StageLimiter pour les oreilles + (path +/+ "Synthdefs.scd").load; // Chargement des synthétiseurs + (path +/+ "Startup.scd").load; // Chargement post-configuration + StageLimiter.activate; // StageLimiter pour les oreilles "=-=-=-=-=-=-=-=-=-=-=".postln; ready.postln; "=-=-=-=-=-=-=-=-=-=-=".postln; diff --git a/Classes/BuboObject.sc b/Classes/BuboObject.sc index e5c4ebb..de19835 100644 --- a/Classes/BuboObject.sc +++ b/Classes/BuboObject.sc @@ -1,5 +1,7 @@ Panic { + *new { CmdPeriod.run; } + } diff --git a/Classes/BuboPbind.sc b/Classes/BuboPbind.sc index 1d6c259..d666a1b 100644 --- a/Classes/BuboPbind.sc +++ b/Classes/BuboPbind.sc @@ -1,23 +1,2 @@ + Pbind { - fastest { ^this.set(\dur, 1/8) } - faster { ^this.set(\dur, 1/4) } - fast { ^this.set(\dur, 1/2) } - slow { ^this.set(\dur, 2) } - slower { ^this.set(\dur, 4) } - slowest { ^this.set(\dur, 8) } - - lowest { ^this.set(\octave, 2) } - lower { ^this.set(\octave, 3) } - low { ^this.set(\octave, 4) } - high { ^this.set(\octave, 6) } - higher { ^this.set(\octave, 7) } - highest { ^this.set(\octave, 8) } - - fff { ^this.set(\amp, 2) } - ff { ^this.set(\amp, 1) } - f { ^this.set(\amp, 0.5) } - p { ^this.set(\amp, 0.3) } - pp { ^this.set(\amp, 0.2) } - ppp { ^this.set(\amp, 0.1) } } - diff --git a/Classes/StageLimiter.sc b/Classes/StageLimiter.sc new file mode 100644 index 0000000..7f89056 --- /dev/null +++ b/Classes/StageLimiter.sc @@ -0,0 +1,39 @@ +//Batuhan Bozkurt 2009 +StageLimiter +{ + classvar lmSynth, lmFunc, activeSynth; + + *activate + { |numChannels = 2| + fork + { + lmFunc = + { + { + activeSynth = + Synth(\stageLimiter, + target: RootNode(Server.default), + addAction: \addToTail + ); + }.defer(0.01) + }; + lmSynth = SynthDef(\stageLimiter, + { + var input = In.ar(0, numChannels); + input = Select.ar(CheckBadValues.ar(input, 0, 0), [input, DC.ar(0), DC.ar(0), input]); + ReplaceOut.ar(0, Limiter.ar(input)) ; + }).add; + Server.default.sync; + lmFunc.value; + CmdPeriod.add(lmFunc); + "StageLimiter active".postln; + } + } + + *deactivate + { + activeSynth.free; + CmdPeriod.remove(lmFunc); + "StageLimiter inactive...".postln; + } +} diff --git a/Classes/Startup.scd b/Classes/Startup.scd new file mode 100644 index 0000000..3eb940e --- /dev/null +++ b/Classes/Startup.scd @@ -0,0 +1,3 @@ +c = currentEnvironment.clock; +MIDIClient.init; +m = MIDIOut.newByName("MIDI", "Bus 1"); diff --git a/Classes/Synthdefs.scd b/Classes/Synthdefs.scd new file mode 100644 index 0000000..73e2792 --- /dev/null +++ b/Classes/Synthdefs.scd @@ -0,0 +1,291 @@ +d = (); // This is a storage area for synthesizers +f = (); // This is a storage for various FX functions + +( +d.info = { arg obj, name; obj[name].allControlNames.do({arg i; i.postln;}); }; +d.show = { arg obj; obj.keys.do({arg i; i.postln}); }; +); + +f.vardel = { + arg in; + HPF.ar(CombC.ar(in, 2, c.beatDur / [1, 2], 2), + SinOsc.ar(c.beatDur * 4).range(500, 2000)); +}; + +( + z = SynthDef.new(\sampler, { + arg buf, rate=1, amp=1, pan=0, attack=0.01, release=1, loop=0; + var sig; + var env = EnvGen.ar(Env.perc(attack, release, doneAction: 2)); + var startPos = 0; + sig = PlayBuf.ar( + numChannels: 1, + bufnum: buf, + rate:BufRateScale.kr(buf) * rate, + trigger: 1, startPos:startPos, + loop:loop, doneAction: 2); + sig = sig * amp; + sig = Pan2.ar(sig * env, pan); + Out.ar(0, sig); + }).add; + d.sampler = z; +); + + +( + z = SynthDef.new(\revsampler, { + arg buf, rate=1, amp=1, pan=0, attack=0.01, release=1, loop=1; + var sig; + var env = EnvGen.ar(Env.perc(attack, release, doneAction: 2)); + var startPos = 0; + sig = PlayBuf.ar( + numChannels: 1, + bufnum: buf, + rate:BufRateScale.kr(buf) * rate, + trigger: 1, startPos:startPos, + loop:loop, doneAction: 2); + sig = sig * amp; + sig = Pan2.ar(sig * env, pan); + Out.ar(0, sig); + }).add; + d.revsampler = z; +); + +( + z = SynthDef(\sinfb, { + arg freq = 440, atk = 0.01, sus = 0, rel = 1, fb = 0, amp = 0.3, out = 0, pan=0; + var sig, env; + env = EnvGen.ar(Env.linen(atk,sus,rel),1,1,0,1,2); + sig = SinOscFB.ar(freq,fb,1); + sig = sig*env; + Out.ar(out,Pan2.ar(sig,pan,amp)); + }).add; + d.sinfb = z; +); + +( + z = SynthDef(\kick2, { + var snd; + snd = DC.ar(0); + snd = snd + (HPF.ar(Hasher.ar(Sweep.ar), 1320) * Env.perc(0.003, 0.03).ar * 0.5); + snd = snd + (SinOsc.ar(XLine.ar(750, 161, 0.02)) * Env.perc(0.0005, 0.02).ar); + snd = snd + (SinOsc.ar(XLine.ar(167, 52, 0.04)) * Env.perc(0.0005, 0.3).ar(2)); + snd = snd.tanh; + Out.ar(\out.kr(0), Pan2.ar(snd, \pan.kr(0), \amp.kr(0.9))); + }).add; + d.kick2 = z; +); + +( + z = SynthDef(\kick3, { + var snd; + snd = DC.ar(0); + snd = snd + (SinOsc.ar(XLine.ar(1500, 800, 0.01)) * Env.perc(0.0005, 0.01, curve: \lin).ar); + snd = snd + (BPF.ar(Impulse.ar(0) * SampleRate.ir / 48000, 6100, 1.0) * 3.dbamp); + snd = snd + (BPF.ar(Hasher.ar(Sweep.ar), 300, 0.9) * Env.perc(0.001, 0.02).ar); + snd = snd + (SinOsc.ar(XLine.ar(472, 60, 0.045)) * Env.perc(0.0001, 0.3, curve: \lin).delay(0.005).ar(2)); + snd = snd.tanh; + Out.ar(\out.kr(0), Pan2.ar(snd, \pan.kr(0), \amp.kr(0.1))); + }).add; + d.kick3 = z; +); + + +( + z = SynthDef("snare", {arg amp = 0.1, freq = 100, att = 0.01, rel = 0.2, ffreq = 2000, pan = 0; + var env, snd1, snd2, sum; + env = Env.perc(att, rel, amp).kr; + snd1 = HPF.ar( + in: WhiteNoise.ar, + freq: ffreq + ); + snd2 = SinOsc.ar(freq: freq); + sum = snd1 + snd2; + sum = sum * env; + Out.ar(0, Pan2.ar(sum, pan)); + DetectSilence.ar(sum, doneAction: 2); + }).add; + d.snare = z; +); + + +( + z = SynthDef("hihat", {arg amp = 0.5, att = 0.01, rel = 0.2, ffreq = 6000, pan = 0; + var env, snd; + env = Env.perc( + attackTime: att, + releaseTime: rel, + level: amp*1.2 + ).kr; + snd = WhiteNoise.ar; + snd = HPF.ar(in: snd, freq: ffreq); + snd = snd * env; + Out.ar(0, Pan2.ar(snd, pan)); + DetectSilence.ar(snd, doneAction: 2); + }).add; + d.hihat = z; +); + +( + z = SynthDef(\kick1, { + var snd; + snd = DC.ar(0); + snd = snd + (SinOsc.ar(XLine.ar(800, 400, 0.01)) * Env.perc(0.0005, 0.01).ar); + snd = snd + (BPF.ar(Hasher.ar(Sweep.ar), XLine.ar(800, 100, 0.01), 0.6) * Env.perc(0.001, 0.02).delay(0.001).ar); + snd = snd + (SinOsc.ar(XLine.ar(172, 50, 0.01)) * Env.perc(0.0001, 0.3, 1, \lin).delay(0.005).ar(2)); + snd = snd.tanh; + Out.ar(\out.kr(0), Pan2.ar(snd, \pan.kr(0), \amp.kr(0.1))); + }).add; + d.kick1 = z; +); + +( + z = SynthDef(\braids, {|out=0,freq=440,amp=0.5,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0,timbre=0.5,color=0.5,model=0| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiBraids.ar(pitch: freq.cpsmidi, timbre: timbre, color: color, model: model); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.braids = z; +); + +( + z = SynthDef(\omi, {|out=0,freq=440,amp=0.5,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiOmi.ar(pit: freq.cpsmidi); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.omi = z; +); + + +( + [ + 'analog', 'waveshape', + 'fm', 'grain', + 'additive', 'wavetable', + 'chord', 'speech', + 'swarm', 'noise', + 'particle', 'string', + 'modal', 'bass', + 'snare', 'hat' + ].do({arg name, index; + var synth; + [name, index].postln; + synth = SynthDef(name, {|out=0,freq=440,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0, + amp=0.5,timbre=0.5,harm=0.5,morph=0.5,level=1,lpgdecay=0,lpgcolour=0,mode=0| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiPlaits.ar( + pitch: freq.cpsmidi, + timbre: timbre, + harm: harm, + engine: index, + morph: morph, + level: level, + decay: lpgdecay, + lpg_colour: lpgcolour, + ); + sig = Select.ar(mode, sig); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.put(name, synth); + }); +); + +( + ['csaw', 'morph', 'saw_square', 'sine_triangle', + 'buzz', 'square_sub', 'saw_sub', 'square_sync', + 'saw_sync', 'triple_saw', 'triple_square', + 'triple_triangle', 'triple_sine', 'triple_ring_mod', + 'saw_swarm', 'saw_comb', 'toy', 'filter_lp', + 'filter_pk', 'filter_bp', 'filter_hp', 'vosim', + 'vowel', 'vowel_fof', 'harmonics', 'bfm', 'feedback_fm', + 'chaotic_feedback_fm', 'plucked', 'bowed', 'blown', 'fluted', + 'struck_bell', 'struck_drum', 'bkick', 'cymbal', 'bsnare', + 'bwavetable', 'wave_map', 'wave_line', 'wave_paraphonic', + 'filtered_noise', 'twin_peaks_noise', 'clocked_noise', + 'granular_cloud', 'particle_noise', 'digital_modulation', + 'question_mark'].do({ + arg name, index; + var synth; + synth = SynthDef(name, {|out=0,freq=440,amp=0.5,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0,timbre=0.5,color=0.5,ws=0,bits=0, resamp=0, decim=32| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiBraids.ar(pitch: freq.cpsmidi, timbre: timbre, resamp: 0, decim: decim, color: color, model: index, ws: ws, bits:bits); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.put(name, synth); + }); +); + +( + z = SynthDef(\plaits, {|out=0,freq=440,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0, + amp=0.5,timbre=0.5,engine=0,harm=0.5,morph=0.5,level=1,lpgdecay=0,lpgcolour=0,mode=0| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiPlaits.ar( + pitch: freq.cpsmidi, + timbre: timbre, + harm: harm, + engine: engine, + morph: morph, + level: level, + decay: lpgdecay, + lpg_colour: lpgcolour, + ); + sig = Select.ar(mode, sig); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.plaits = z; +); + +( + z = SynthDef(\tides, {|out=0,freq=440,amp=0.5,sustain=1,pan=0,begin=0,end=1,speed=1,accelerate=0,tidesshape=0.5,slope=0.5,tidessmooth=0.5,shift=0.5,mode=2| + var envLength = sustain*(end-begin)/speed; + var line = Line.ar(begin, end, envLength, doneAction: Done.freeSelf); + var env = Env.asr; + var volume = IEnvGen.ar(env, line) * amp; + var sig; + + freq = max(0, freq * speed * (1 + (accelerate * line))); + sig = MiTides.ar( + freq: freq, + shape: tidesshape, + slope: slope, + smooth: tidessmooth, + shift: shift, + output_mode: mode, + ramp_mode: 1, + rate: 1 + ); + Out.ar(out, Pan2.ar(sig * volume, pan)); + }).add; + d.tides = z; +); + +z = nil; // We don't need that variable anymore diff --git a/README.md b/README.md index 03c28f5..6cac3fd 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Quarks.install("https://github.com/Bubobubobubobubo/BuboQuark") ## Usage -This quark brings syntax shortcuts and minor improvements (_highly personal matter_) to make **SuperCollider** easier to handle on stage. +This quark brings syntax shortcuts and minor improvements (_highly personal matter_) to make **SuperCollider** easier to handle on stage. ### Boot method @@ -25,8 +25,23 @@ applications - set paths for samples and synthdefs - install a `StageLimiter` not to blow up my speakers +The `LinkClock` is accessible through the `c` global variable. + **Note:** I put my configuration into `./config/livecoding/` and there should be a folder named `samples/` and a file called `Synthdefs.scd`. +### Events + +I am using some Events as classes to store some of the things I want to load with each session (FX templates, SynthDef reference, etc). I am using : + +- `d`: **D**efinitions (`SynthDefs`) +- `f`: **F**X templates (DSP functions with a simple name) + +To use one of the effects, you can use the following syntax: + +```supercollider +~my_ndef.fx(100, 0.5, f[\vardel]); +``` + ### Simplified useful commands - `Panic()`: shortcut for `CmdPeriod.run`.