diff --git a/BuboQuark.quark b/BuboQuark.quark index 1c1db41..93f4790 100644 --- a/BuboQuark.quark +++ b/BuboQuark.quark @@ -10,6 +10,7 @@ schelp: "BuboQuark", dependencies: [ "https://github.com/cappelnord/BenoitLib", + "https://github.com/j0py/Pmini", "https://github.com/scztt/Singleton.quark", "https://github.com/scztt/Require.quark", "https://github.com/dmorgan-github/Pdv", diff --git a/Classes/BuboBoot.sc b/Classes/BuboBoot.sc index 4ae3929..c16c71b 100644 --- a/Classes/BuboBoot.sc +++ b/Classes/BuboBoot.sc @@ -7,7 +7,8 @@ Boot { *new { arg configPath, samplePath, serverOptions; - var p; var c; var t; var s; var d; var e; + var p; var c; var t; var s; var d; var e; var b; + Server.killAll; BuboUtils.fancyPrint(BuboUtils.banner, 40); MIDIClient.init; @@ -43,30 +44,34 @@ Boot { this.localPath = this.class.filenameSymbol.asString.dirname +/+ "Configuration"; p = ProxySpace.push(s.boot, clock: this.clock); + p.quant = 4; p.fadeTime = 0.01; this.samplePath = samplePath ? "/Users/bubo/.config/livecoding/samples"; // Setting up the audio samples/buffers manager Bank.lazyLoading = true; Bank.root = this.samplePath; + // Post actions: installing behavior after server boot Server.default.waitForBoot({ - // d = (); - // // Exceptional Dual Sardine Boot - // d.dirt = SuperDirt(2, s); - // d.dirt.fileExtensions = ["wav","aif","aiff","aifc","mp3"]; - // d.dirt.loadSoundFiles("/Users/bubo/Library/Application\ Support/Sardine/SON/*"); - // d.dirt.loadSoundFiles("/Users/bubo/.config/livecoding/samples/*"); - // d.dirt.doNotReadYet = true; - // d.dirt.start(57120, [ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22]); - // ( - // d.d1 = d.dirt.orbits[0]; d.d2 = d.dirt.orbits[1]; d.d3 = d.dirt.orbits[2]; - // d.d4 = d.dirt.orbits[3]; d.d5 = d.dirt.orbits[4]; d.d6 = d.dirt.orbits[5]; - // d.d7 = d.dirt.orbits[6]; d.d8 = d.dirt.orbits[7]; d.d9 = d.dirt.orbits[8]; - // d.d10 = d.dirt.orbits[9]; d.d11 = d.dirt.orbits[10]; d.d12 = d.dirt.orbits[11]; - // ); - // d.dirt.soundLibrary.addMIDI(\midi, MIDIOut.newByName("MIDI", "Bus 1")); - // d.dirt.soundLibrary.addMIDI(\midi2, MIDIOut.newByName("MIDI", "Bus 2")); + if (false) { + d = (); + // Exceptional Dual Sardine Boot + d.dirt = SuperDirt(2, s); + d.dirt.fileExtensions = ["wav","aif","aiff","aifc","mp3"]; + d.dirt.loadSoundFiles("/Users/bubo/Library/Application\ Support/Sardine/SON/*"); + d.dirt.loadSoundFiles("/Users/bubo/.config/livecoding/samples/*"); + d.dirt.doNotReadYet = true; + d.dirt.start(57120, [ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22]); + ( + d.d1 = d.dirt.orbits[0]; d.d2 = d.dirt.orbits[1]; d.d3 = d.dirt.orbits[2]; + d.d4 = d.dirt.orbits[3]; d.d5 = d.dirt.orbits[4]; d.d6 = d.dirt.orbits[5]; + d.d7 = d.dirt.orbits[6]; d.d8 = d.dirt.orbits[7]; d.d9 = d.dirt.orbits[8]; + d.d10 = d.dirt.orbits[9]; d.d11 = d.dirt.orbits[10]; d.d12 = d.dirt.orbits[11]; + ); + d.dirt.soundLibrary.addMIDI(\midi, MIDIOut.newByName("MIDI", "Bus 1")); + d.dirt.soundLibrary.addMIDI(\midi2, MIDIOut.newByName("MIDI", "Bus 2")); + }; s.latency = 0.3; // Resume normal boot sequence @@ -80,6 +85,9 @@ Boot { Safety.setLimit(1); e = currentEnvironment; + // Setting up the archive + "Retrieving code archives".postln; + b = Archive.global.at(\bubo); }); diff --git a/Classes/BuboNodeProxy.sc b/Classes/BuboNodeProxy.sc index 85f01f7..60541ad 100644 --- a/Classes/BuboNodeProxy.sc +++ b/Classes/BuboNodeProxy.sc @@ -1,3 +1,4 @@ + + NodeProxy { /* Simple FX chain management */ @@ -10,15 +11,15 @@ ^this; } - fx1 { arg wet, function; this.fx(100, wet, function); } - fx2 { arg wet, function; this.fx(200, wet, function); } - fx3 { arg wet, function; this.fx(300, wet, function); } - fx4 { arg wet, function; this.fx(400, wet, function); } - fx5 { arg wet, function; this.fx(500, wet, function); } - fx6 { arg wet, function; this.fx(600, wet, function); } - fx7 { arg wet, function; this.fx(700, wet, function); } - fx8 { arg wet, function; this.fx(800, wet, function); } - fx9 { arg wet, function; this.fx(900, wet, function); } + fx1 { arg wet=0.5, function; this.fx(100, wet, function); } + fx2 { arg wet=0.5, function; this.fx(200, wet, function); } + fx3 { arg wet=0.5, function; this.fx(300, wet, function); } + fx4 { arg wet=0.5, function; this.fx(400, wet, function); } + fx5 { arg wet=0.5, function; this.fx(500, wet, function); } + fx6 { arg wet=0.5, function; this.fx(600, wet, function); } + fx7 { arg wet=0.5, function; this.fx(700, wet, function); } + fx8 { arg wet=0.5, function; this.fx(800, wet, function); } + fx9 { arg wet=0.5, function; this.fx(900, wet, function); } wet { arg number=1, wet=1; this.set(("wet" ++ number).asSymbol, wet); @@ -37,17 +38,25 @@ ^this; } + prepareToPlay { + | proxy, quant, fade | + proxy.quant = quant; + proxy.fadeTime = fade; + // proxy.play; + } + /* Syntax for sending MIDI messages */ >> { arg pattern; var quant = this.getQuantFromPattern(pattern); var fade = this.getFadeFromPattern(pattern); - pattern = EventShortener.findShortcuts(pattern); - pattern = pattern ++ [type: 'midi']; + pattern = EventShortener.process( + pattern, + this.key, + [type: 'midi'] + ); this[0] = Pbind(*pattern); - this.quant = quant; - this.fadeTime = fade; - this.play; + this.prepareToPlay(this, quant, fade); ^this } @@ -56,43 +65,50 @@ arg pattern; var quant = this.getQuantFromPattern(pattern); var fade = this.getFadeFromPattern(pattern); - pattern = EventShortener.findShortcuts(pattern); - pattern = pattern ++ [\type, \buboEvent]; + pattern = EventShortener.process( + pattern, + this.key, + [\type, \buboEvent] + ); this[0] = Pbind(*pattern); - this.quant = quant; - this.fadeTime = fade; - this.play; + this.prepareToPlay(this, quant, fade); ^this } /* Audio Looper (sample playback) */ == { + // TODO: fix this terrible mess arg pattern; var quant = this.getQuantFromPattern(pattern); var fade = this.getFadeFromPattern(pattern); - pattern = EventShortener.findShortcuts(pattern); - pattern = pattern ++ [\type, \buboLoopEvent]; - pattern = pattern ++ [\legato, 1]; - pattern = pattern ++ [ - \time, Pkey(\dur) / Pfunc { currentEnvironment.clock.tempo } - ]; - this[0] = Pbind(*pattern); - this.quant = quant; - this.fadeTime = fade; - this.play; + var nbSlices = this.getValueFromPattern(pattern, 'slices', 1); + var time = (Pkey(\dur) / Pfunc { currentEnvironment.clock.tempo }) / nbSlices; + pattern = EventShortener.process( + pattern, + this.key, + [ + \type, \buboLoopEvent, + \legato, 1, + \time, time + ] + ); + this[0] = Pmono(*pattern); + this.prepareToPlay(this, quant, fade); ^this } - /* FIX: Rewrite this part, slightly broken */ + /* Pmono player */ -> { arg pattern; var quant = this.getQuantFromPattern(pattern); var fade = this.getFadeFromPattern(pattern); - pattern = EventShortener.findShortcuts(pattern); + pattern = EventShortener.processPmono( + pattern, + this.key + ); this[0] = Pmono(*pattern); - this.quant = quant; - this.fadeTime = fade; - this.play; + this.prepareToPlay(this; quant, fade); + ^this } f { @@ -121,24 +137,25 @@ ^this } - getQuantFromPattern { - arg pattern; var quant; - var quantIndex = pattern.indexOf('quant'); - if (quantIndex.notNil) { - ^pattern[quantIndex + 1] + getValueFromPattern { + arg pattern, key, default; + var keyIndex = pattern.indexOf(key); + if (keyIndex.notNil) { + ^pattern[keyIndex + 1] } { - ^0 + ^default } } + getQuantFromPattern { + arg pattern; + ^this.getValueFromPattern(pattern, 'quant', 4) + } + getFadeFromPattern { - arg pattern; var fade; - var fadeIndex = pattern.indexOf('fade'); - if (fadeIndex.notNil) { - ^pattern[fadeIndex + 1] - } { - ^0.01 - } + arg pattern; + ^this.getValueFromPattern(pattern, 'fade', 0.01) } + } diff --git a/Classes/Configuration/Synthdefs.scd b/Classes/Configuration/Synthdefs.scd index 959c405..f78912a 100644 --- a/Classes/Configuration/Synthdefs.scd +++ b/Classes/Configuration/Synthdefs.scd @@ -18,7 +18,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; rate:BufRateScale.kr(buf) * (\rate.kr(1) * \freq.kr(400) / 60.midicps), trigger: 1, startPos:startPos, loop:\loop.kr(0), doneAction: 2); - sig = sig * \amp.kr(-6.dbamp); + sig = sig * \amp.kr(-6).dbamp; sig = Pan2.ar(sig * env, \pan.kr(0)); OffsetOut.ar(out, sig) }).add; @@ -46,7 +46,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; rate:BufRateScale.kr(buf) * (\rate.kr(1) * \freq.kr(400) / 60.midicps), trigger: 1, startPos:startPos, loop:\loop.kr(0), doneAction: 2); - sig = sig * \amp.kr(-6.dbamp); + sig = sig * \amp.kr(-6).dbamp; sig = Pan2.ar(sig * env, \pan.kr(0)); OffsetOut.ar(out, sig) }).add; @@ -72,7 +72,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; Env.asr(0.01, 1, 0.01), \gate.kr(1), doneAction: 2 ); sig = sig * env; - sig = sig * \amp.kr(-6.dbamp); + sig = sig * \amp.kr(-6).dbamp; OffsetOut.ar(out,Pan2.ar(sig,\pan.kr(0))); }).add; d.looperMono = z; @@ -96,7 +96,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; Env.asr(0.01, 1, 0.01), \gate.kr(1), doneAction: 2 ); sig = sig * env; - sig = sig * \amp.kr(-6.dbamp); + sig = sig * \amp.kr(-6).dbamp; OffsetOut.ar(out,Pan2.ar(sig,\pan.kr(0))); }).add; d.looperStereo = z; @@ -118,7 +118,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; 1 ); sig = sig * env; - OffsetOut.ar(out, Pan2.ar(sig, \pan.kr(0), \amp.kr(-6.dbamp))); + OffsetOut.ar(out, Pan2.ar(sig, \pan.kr(0), \amp.kr(-6).dbamp)); }).add; d.sinfb = z; ); @@ -129,7 +129,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; var envLength = \sustain.kr(1) * (\end.kr(1) - \begin.kr(0)) / \speed.kr(1); var line = Line.ar(\begin.kr, \end.kr, envLength, doneAction: Done.freeSelf); var env = Env.asr; - var volume = IEnvGen.ar(env, line) * \amp.kr(-6.dbamp); + var volume = IEnvGen.ar(env, line) * \amp.kr(-6).dbamp; var sig; sig = MiOmi.ar(pit: \freq.kr(400).cpsmidi); OffsetOut.ar(out, Pan2.ar(sig * volume, \pan.kr(0))); @@ -168,7 +168,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; lpg_colour: \lpgcolour.kr(0), ); sig = Pan2.ar(sig[0], \pan.kr(0)); - sig = sig * env * \amp.kr(-6.dbamp); + sig = sig * env * \amp.kr(-6).dbamp; OffsetOut.ar(out, sig); }).add; d.put(name, synth); @@ -243,7 +243,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; ws: \ws.kr(0), bits: \bits.kr(0) ); - OffsetOut.ar(out, Pan2.ar(sig * env * \amp.kr(-6.dbamp), \pan.kr(0))); + OffsetOut.ar(out, Pan2.ar(sig * env * \amp.kr(-6).dbamp, \pan.kr(0))); }).add; d.put(name, synth); }); @@ -264,7 +264,7 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; rate: 1 ); OffsetOut.ar(out, - Pan2.ar(sig * env * \amp.kr(-6.dbamp), + Pan2.ar(sig * env * \amp.kr(-6).dbamp, \pan.kr(0) )); }).add; @@ -294,18 +294,18 @@ d.list = { arg obj; obj.keys.do({arg i; i.postln}); }; ( z = SynthDef('kick', { - arg out, freq, mul=512, vsweep=0.5, hold=0.25, release=0.25, amp=0.5, pan=0; + arg out; var p0, p1, p, freq0, freq1, freqEnv, sig; p0 = 0.006699687; p1 = 0.00001884606; - p = (1-vsweep)*p0 + (vsweep*p1); - freq1 = freq; - freq0 = freq1 * mul; + p = (1-\vsweep.kr(0.5)) * p0 + (\vsweep.kr * p1); + freq1 = \freq.kr(100); + freq0 = freq1 * \mul.kr(20); freqEnv = EnvGen.ar(Env([0,1], [1.0], [0])); freqEnv = freq1 + ((freq0-freq1)/(1.0 + (freqEnv/p))); sig = SinOsc.ar(freqEnv); - sig = sig * EnvGen.ar(Env([1,1,0], [hold,release], [0,0]), doneAction: Done.freeSelf) * amp; - sig = Pan2.ar(sig, pan); + sig = sig * EnvGen.ar(Env([1,1,0], [\hold.kr(0.25), \release.kr(0.5)], [0,0]), doneAction: Done.freeSelf) * \amp.kr(-6).dbamp; + sig = Pan2.ar(sig, \pan.kr(0.0)); OffsetOut.ar(out, sig); }).add; d.kick = z; diff --git a/Classes/EventShortener.sc b/Classes/EventShortener.sc index ef564c7..6d01dce 100644 --- a/Classes/EventShortener.sc +++ b/Classes/EventShortener.sc @@ -1,5 +1,76 @@ EventShortener { + *process { + arg pattern, key, other_keys; + if (pattern.includes('pat'), { + pattern = this.patternize(pattern); + }); + pattern = this.findShortcuts(pattern); + pattern = this.functionsToNdef(pattern, key); + pattern = pattern ++ other_keys ; + ^pattern + } + + *patternize { + arg pattern; + var delta_index = nil; + var new_pattern = List(); + pattern.doAdjacentPairs({ + arg a, b, index; + if (index % 2 == 0, { + if (a === 'pat', { + var temp = Pmini(b); + temp.pattern.postln; + new_pattern = new_pattern ++ [ + [\trig, \delta, \dur, \str, \num], + temp + ]; + new_pattern = new_pattern ++ [ + degree: Pfunc({ |e| + if (e.trig > 0, { + e.str.asInteger + }, { + \rest + } + )}); + ]; + if (pattern.includes('i') || pattern.includes('instrument') == false, { + new_pattern = new_pattern ++ [ + sp: Pkey(\str), + nb: Pkey(\num), + fast: 1, + ]; + }); + }, { + new_pattern.add(a); + new_pattern.add(b); + }); + }) + }); + ^new_pattern + } + + *processPmono { + arg pattern, key; + pattern = this.findShortcuts(pattern); + pattern = this.functionsToNdef(pattern, key); + ^pattern + } + + *functionsToNdef { + arg pattern, key; + var new_pattern = List.new(); + pattern.do({ + | element, i | + if (element.isKindOf(Function), { + new_pattern.add(Ndef((key ++ pattern[i - 1]).asSymbol, element)) + }, { + new_pattern.add(element) + }); + }) + ^new_pattern + } + *findShortcuts { arg pattern; var short, correctedPattern; @@ -38,13 +109,13 @@ EventShortener { \scl, \scale, ]); - // shortcuts are turned into regular keys; - pattern.do({| element | + pattern.do({| element, i | if (short.includesKey(element), {correctedPattern.add(short[element])}, {correctedPattern.add(element)} ); }); + ^correctedPattern; } } diff --git a/Classes/PseudoUgen/Chorus.sc b/Classes/PseudoUgen/Chorus.sc new file mode 100644 index 0000000..7fe5abd --- /dev/null +++ b/Classes/PseudoUgen/Chorus.sc @@ -0,0 +1,6 @@ +Chorus { + *ar { + + } +} + diff --git a/Classes/PseudoUgen/Compressor.sc b/Classes/PseudoUgen/Compressor.sc new file mode 100644 index 0000000..4c5aa53 --- /dev/null +++ b/Classes/PseudoUgen/Compressor.sc @@ -0,0 +1,11 @@ +// TODO: broken +Compressor { + *ar { + arg signal, attack, release, threshold, ratio; + var gainDb, amplitudeDb; + amplitudeDb = Amplitude.ar(signal, attack, release).ampdb; + gainDb = ((amplitudeDb - threshold) * (1 / ratio - 1)).min(0); + signal = signal * gainDb.dbamp; + signal + } +} diff --git a/Classes/PseudoUgen/Phaser.sc b/Classes/PseudoUgen/Phaser.sc new file mode 100644 index 0000000..5793dee --- /dev/null +++ b/Classes/PseudoUgen/Phaser.sc @@ -0,0 +1,12 @@ +BuboPhaser { + * ar { + arg signal, speed=2, skew=0, feedback=0.25, mod=0.5; + ^AnalogPhaser.ar( + input: signal, + lfoinput: LFNoise2.ar(speed).range(-1, 1), + skew: skew.clip2(1), + feedback: feedback.clip2(1), + modulation: mod.clip2(1) + ) + } +} diff --git a/Classes/PseudoUgen/StereoWah.sc b/Classes/PseudoUgen/StereoWah.sc new file mode 100644 index 0000000..6eb47c8 --- /dev/null +++ b/Classes/PseudoUgen/StereoWah.sc @@ -0,0 +1,9 @@ +StereoWah { + *ar { + arg signal, leftSpeed, rightSpeed; + ^[ + signal[0] * SinOsc.ar(leftSpeed).range(0.1, 1), + signal[1] * SinOsc.ar(rightSpeed).range(0.1, 1), + ] + } +} diff --git a/Classes/PseudoUgen/Wah.sc b/Classes/PseudoUgen/Wah.sc new file mode 100644 index 0000000..5ec95e4 --- /dev/null +++ b/Classes/PseudoUgen/Wah.sc @@ -0,0 +1,5 @@ +Wah { + *ar { arg signal, speed; + ^(signal * SinOsc.ar(speed).range(0.1, 1)) + } +}