Synchronising for Rémi
This commit is contained in:
@ -10,98 +10,70 @@
|
||||
^Pindex(pat, this[1], repeats)
|
||||
}
|
||||
|
||||
findShortcuts {
|
||||
arg pattern;
|
||||
var short, correctedPattern;
|
||||
correctedPattern = List.new();
|
||||
short = Dictionary.newFrom([
|
||||
// Instrument
|
||||
\i, \instrument,
|
||||
// Notes
|
||||
\n, \note,
|
||||
\mn, \midinote,
|
||||
\vel, \velocity,
|
||||
\deg, \degree,
|
||||
\off, \timingOffset,
|
||||
\o, \octave,
|
||||
\f, \freq,
|
||||
\det, \detune,
|
||||
// Durations
|
||||
\d, \dur,
|
||||
\l, \legato,
|
||||
// Amplitude
|
||||
\p, \pan,
|
||||
// Envelope
|
||||
\a, \attack,
|
||||
\d, \decay,
|
||||
\s, \sustain,
|
||||
\r, \release,
|
||||
// Filter control
|
||||
\r, \resonance,
|
||||
\ff, \ffreq,
|
||||
// Modulation
|
||||
\m, \mod,
|
||||
\mo, \midout,
|
||||
\c, \midichan,
|
||||
\st, \stretch,
|
||||
\rt, \root,
|
||||
\scl, \scale,
|
||||
]);
|
||||
|
||||
// shortcuts are turned into regular keys;
|
||||
pattern.do({| element |
|
||||
if (short.includesKey(element),
|
||||
{correctedPattern.add(short[element])},
|
||||
{correctedPattern.add(element)}
|
||||
);
|
||||
});
|
||||
^correctedPattern;
|
||||
}
|
||||
|
||||
pat {
|
||||
arg quant=4, fade=0.05;
|
||||
var proxyName = this[0];
|
||||
var newArray = this[1..] ++ [\type, \buboEvent];
|
||||
currentEnvironment.at(proxyName.asSymbol).quant_(quant);
|
||||
currentEnvironment.at(proxyName.asSymbol).fadeTime = fade;
|
||||
currentEnvironment.at(proxyName.asSymbol)[0] = Pbind(*(this.findShortcuts(newArray)));
|
||||
currentEnvironment.at(proxyName.asSymbol)[0] = Pbind(*(EventShortener.findShortcuts(newArray)));
|
||||
^currentEnvironment.at(proxyName.asSymbol);
|
||||
}
|
||||
|
||||
pwrap {
|
||||
arg maxIndex, startIndex=0, repeats=inf;
|
||||
^PwrapSeq(this, maxIndex, startIndex, repeats)
|
||||
}
|
||||
|
||||
|
||||
p {
|
||||
^Pbind(*(this.findShortcuts(this)))
|
||||
^Pbind(*(Eventshortener.findShortcuts(this)))
|
||||
}
|
||||
|
||||
euclid {
|
||||
eu {
|
||||
arg repeats=inf;
|
||||
^Pbjorklund2(this[0], this[1], repeats);
|
||||
var divisor = 1;
|
||||
if (this[3] != nil, { divisor = this[3] });
|
||||
^Pbjorklund2(this[0], this[1], repeats, this[2]) / divisor;
|
||||
}
|
||||
|
||||
pseq { arg repeats=inf, offset=0;
|
||||
^Pseq(this, repeats, offset);
|
||||
pseq {
|
||||
arg repeats=inf;
|
||||
^Pseq(this, repeats);
|
||||
}
|
||||
|
||||
pshuf { arg repeats=1;
|
||||
pshuf {
|
||||
arg repeats=1;
|
||||
^Pshuf(this, repeats);
|
||||
}
|
||||
|
||||
prand { arg repeats=inf;
|
||||
prand {
|
||||
arg repeats=inf;
|
||||
^Prand(this, repeats);
|
||||
}
|
||||
|
||||
pxrand { arg repeats=inf;
|
||||
pxrand {
|
||||
arg repeats=inf;
|
||||
^Pxrand(this, repeats);
|
||||
}
|
||||
|
||||
pwrand { arg weights, repeats=1;
|
||||
pwrand {
|
||||
arg weights, repeats=1;
|
||||
^Pwrand(this, weights.normalizeSum, repeats);
|
||||
}
|
||||
|
||||
pwhite { arg repeats=inf;
|
||||
pwhite {
|
||||
arg repeats=inf;
|
||||
^Pwhite(this[0], this[1], repeats);
|
||||
}
|
||||
|
||||
pseries { arg repeats=inf;
|
||||
pseries {
|
||||
arg repeats=inf;
|
||||
^Pseries(this[0], this[1], repeats);
|
||||
}
|
||||
|
||||
pbrown {
|
||||
arg repeats=inf;
|
||||
^Pbrown(this[0], this[1], this[2], repeats);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,13 +8,7 @@ Boot {
|
||||
*new {
|
||||
arg configPath, samplePath, serverOptions;
|
||||
var p; var c; var t; var s;
|
||||
var banner = "┳┓ ┓ ┳┓\n"
|
||||
"┣┫┓┏┣┓┏┓ ┣┫┏┓┏┓╋\n"
|
||||
"┻┛┗┻┗┛┗┛ ┻┛┗┛┗┛┗";
|
||||
var ready = "┓ ┳┓┏┏┓ ┏┓┏┓┳┓┏┓ ┳┓┏┓┏┓┳┓┓┏\n"
|
||||
"┃ ┃┃┃┣ ┃ ┃┃┃┃┣ ┣┫┣ ┣┫┃┃┗┫\n"
|
||||
"┗┛┻┗┛┗┛ ┗┛┗┛┻┛┗┛ ┛┗┗┛┛┗┻┛┗┛";
|
||||
this.fancyPrint(banner, 40);
|
||||
BuboUtils.fancyPrint(BuboUtils.banner, 40);
|
||||
|
||||
if (serverOptions == nil,
|
||||
{
|
||||
@ -55,29 +49,18 @@ Boot {
|
||||
Server.default.waitForBoot({
|
||||
"-> Loading config from: %".format(configPath ? (this.localPath +/+ "Startup.scd")).postln;
|
||||
(configPath ? (this.localPath +/+ "Startup.scd")).load;
|
||||
Safety.setLimit(0.8);
|
||||
this.fancyPrint(ready, 40);
|
||||
Safety.all;
|
||||
Safety(s).defName = \safeLimit;
|
||||
Safety.setLimit(1);
|
||||
BuboUtils.fancyPrint(BuboUtils.ready, 40);
|
||||
this.installServerTreeBehavior();
|
||||
this.clock.enableMeterSync();
|
||||
});
|
||||
}
|
||||
|
||||
*fancyPrint {
|
||||
arg message, length;
|
||||
var separator= length.collect({
|
||||
arg index;
|
||||
if (index % 2 == 0, "=", "-")
|
||||
});
|
||||
separator = separator.join("");
|
||||
[separator, message, separator].do({
|
||||
arg each;
|
||||
each.postln;
|
||||
});
|
||||
}
|
||||
|
||||
*installServerTreeBehavior {
|
||||
CmdPeriod.add({
|
||||
this.fancyPrint("\nBubo SuperCollider Session\nTempo: % | Peers: %\nCPU: % | Peak: %\n".format(
|
||||
BuboUtils.fancyPrint("\nBubo SuperCollider Session\nTempo: % | Peers: %\nCPU: % | Peak: %\n".format(
|
||||
this.clock.tempo * 60, this.clock.numPeers,
|
||||
Server.default.avgCPU.round(2),
|
||||
Server.default.peakCPU.round(2)), 40)
|
||||
@ -88,6 +71,7 @@ Boot {
|
||||
{ ~buf = Bank(~sp)[~nb % Bank(~sp).buffers.size]; }
|
||||
);
|
||||
if (~nb == nil) {~nb = 0};
|
||||
if (~sp == nil) {~sp = 'default'};
|
||||
~type = \note;
|
||||
currentEnvironment.play;
|
||||
});
|
||||
|
||||
16
Classes/BuboEnv.sc
Normal file
16
Classes/BuboEnv.sc
Normal file
@ -0,0 +1,16 @@
|
||||
+ Env {
|
||||
|
||||
*rand {
|
||||
arg numSegs=8, dur=1, bipolar=true;
|
||||
var env, levels, times, curves, minLevel;
|
||||
levels = {rrand(-1.0, 1.0)}!numSegs+1;
|
||||
minLevel = bipolar.asInteger.neg;
|
||||
levels = levels.normalize(minLevel, 1);
|
||||
times = {exprand(1,10)}!numSegs;
|
||||
times = times.normalizeSum * dur;
|
||||
curves = {rrand(-4.0,4.0)}!numSegs;
|
||||
env = this.new(levels, times, curves);
|
||||
^env;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
+ NodeProxy {
|
||||
|
||||
/* Simple FX chain management */
|
||||
|
||||
fx {
|
||||
arg number=1, wet=1, function = {|in| in};
|
||||
this[number] = \filter -> function;
|
||||
@ -34,4 +36,54 @@
|
||||
this.set(("wet" ++ number).asSymbol, wet);
|
||||
^this;
|
||||
}
|
||||
|
||||
/* Player-like syntax sugar */
|
||||
=> {
|
||||
arg pattern;
|
||||
pattern = EventShortener.findShortcuts(pattern);
|
||||
pattern = pattern ++ [\type, \buboEvent];
|
||||
this[0] = Pbind(*pattern);
|
||||
this.quant = 4; this.fadeTime = 0.01;
|
||||
^this
|
||||
}
|
||||
|
||||
/* FIX: Completely broken. What is the event type
|
||||
* BuboEvent should fall back to after tweaking
|
||||
* the pattern to my liking?
|
||||
*/
|
||||
-> {
|
||||
arg pattern;
|
||||
pattern = EventShortener.findShortcuts(pattern);
|
||||
// pattern = pattern ++ [\type, \buboMonoEvent];
|
||||
this[0] = Pmono(*pattern);
|
||||
this.quant = 4;
|
||||
this.fadeTime = 0.01;
|
||||
}
|
||||
|
||||
f {
|
||||
arg value;
|
||||
this.fadeTime = value;
|
||||
^this
|
||||
}
|
||||
|
||||
p {
|
||||
arg quant, fade;
|
||||
this.quant = quant;
|
||||
this.fadeTime = fade;
|
||||
this.play(fadeTime: fade);
|
||||
^this
|
||||
}
|
||||
|
||||
s {
|
||||
arg duration;
|
||||
this.stop(fadeTime: duration)
|
||||
^this
|
||||
}
|
||||
|
||||
/ {
|
||||
arg pattern;
|
||||
this.stop(1);
|
||||
^this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
30
Classes/BuboUtils.sc
Normal file
30
Classes/BuboUtils.sc
Normal file
@ -0,0 +1,30 @@
|
||||
BuboUtils {
|
||||
|
||||
*banner {
|
||||
var banner = "┳┓ ┓ ┳┓\n"
|
||||
"┣┫┓┏┣┓┏┓ ┣┫┏┓┏┓╋\n"
|
||||
"┻┛┗┻┗┛┗┛ ┻┛┗┛┗┛┗";
|
||||
^banner
|
||||
}
|
||||
|
||||
*ready {
|
||||
var ready = "┓ ┳┓┏┏┓ ┏┓┏┓┳┓┏┓ ┳┓┏┓┏┓┳┓┓┏\n"
|
||||
"┃ ┃┃┃┣ ┃ ┃┃┃┃┣ ┣┫┣ ┣┫┃┃┗┫\n"
|
||||
"┗┛┻┗┛┗┛ ┗┛┗┛┻┛┗┛ ┛┗┗┛┛┗┻┛┗┛";
|
||||
^ready
|
||||
}
|
||||
|
||||
*fancyPrint {
|
||||
arg message, length;
|
||||
var separator= length.collect({
|
||||
arg index;
|
||||
if (index % 2 == 0, "=", "-")
|
||||
});
|
||||
separator = separator.join("");
|
||||
[separator, message, separator].do({
|
||||
arg each;
|
||||
each.postln;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,4 +3,4 @@ p = currentEnvironment;
|
||||
c = currentEnvironment.clock;
|
||||
"Loading SynthDefs".postln;
|
||||
"Synthdefs.scd".loadRelative;
|
||||
// m = MIDIOut.newByName("MIDI", "Bus 1");
|
||||
m = MIDIControl();
|
||||
|
||||
@ -16,124 +16,86 @@ f.vardel = {
|
||||
* This is the sampler used for 90% of sampling duties.
|
||||
*/
|
||||
(
|
||||
z = SynthDef.new(\s, {
|
||||
arg buf, out=0, freq=440, rate=1, amp=1, begin=0, end=1, pan=0, attack=0.01, release=1, loop=0;
|
||||
var sig;
|
||||
var env = EnvGen.ar(Env.perc(attack, release, doneAction: 2));
|
||||
var startPos = begin * BufFrames.kr(buf);
|
||||
var endPos = end * BufFrames.kr(buf); // TODO: unused
|
||||
z = SynthDef.new(\player, {
|
||||
arg buf;
|
||||
var sig, env = EnvGen.ar(
|
||||
Env.perc(
|
||||
\attack.kr(0.01),
|
||||
\release.kr(1),
|
||||
doneAction: 2)
|
||||
);
|
||||
var startPos = \begin.kr(0) * BufFrames.kr(buf);
|
||||
var endPos = \end.kr(1) * BufFrames.kr(buf); // TODO: unused
|
||||
sig = PlayBuf.ar(
|
||||
numChannels: 1,
|
||||
bufnum: buf,
|
||||
rate:BufRateScale.kr(buf) * (rate * freq / 60.midicps),
|
||||
rate:BufRateScale.kr(buf) * (\rate.kr(1) * \freq.kr(400) / 60.midicps),
|
||||
trigger: 1, startPos:startPos,
|
||||
loop:loop, doneAction: 2);
|
||||
sig = sig * amp;
|
||||
sig = Pan2.ar(sig * env, pan);
|
||||
OffsetOut.ar(out, sig)
|
||||
loop:\loop.kr(0), doneAction: 2);
|
||||
sig = sig * \amp.kr(-6.dbamp);
|
||||
sig = Pan2.ar(sig * env, \pan.kr(0));
|
||||
OffsetOut.ar(\out.kr(0), sig)
|
||||
}).add;
|
||||
d.s = z;
|
||||
d.player = z;
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Stereo variant
|
||||
*/
|
||||
(
|
||||
z = SynthDef.new(\splayer, {
|
||||
arg buf;
|
||||
var sig, env = EnvGen.ar(
|
||||
Env.perc(
|
||||
\attack.kr(0.01),
|
||||
\release.kr(1),
|
||||
doneAction: 2)
|
||||
);
|
||||
var startPos = \begin.kr(0) * BufFrames.kr(buf);
|
||||
var endPos = \end.kr(1) * BufFrames.kr(buf); // TODO: unused
|
||||
sig = PlayBuf.ar(
|
||||
numChannels: 2,
|
||||
bufnum: buf,
|
||||
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 = Pan2.ar(sig * env, \pan.kr(0));
|
||||
OffsetOut.ar(\out.kr(0), sig)
|
||||
}).add;
|
||||
d.splayer = 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));
|
||||
env = EnvGen.ar(
|
||||
Env.linen(
|
||||
\attack.kr(0.01),
|
||||
\sustain.kr(0),
|
||||
\release.kr(1)
|
||||
),1,1,0,1,2);
|
||||
sig = SinOscFB.ar(
|
||||
\freq.kr(400),
|
||||
\fb.kr(0),
|
||||
1
|
||||
);
|
||||
sig = sig * env;
|
||||
OffsetOut.ar(\out.kr(0), Pan2.ar(sig, \pan.kr(0), \amp.kr(-6.dbamp)));
|
||||
}).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(\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);
|
||||
z = SynthDef(\omi, {
|
||||
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;
|
||||
var volume = IEnvGen.ar(env, line) * \amp.kr(-6.dbamp);
|
||||
var sig;
|
||||
|
||||
freq = max(0, freq * speed * (1 + (accelerate * line)));
|
||||
sig = MiOmi.ar(pit: freq.cpsmidi);
|
||||
Out.ar(out, Pan2.ar(sig * volume, pan));
|
||||
sig = MiOmi.ar(pit: \freq.kr(400).cpsmidi);
|
||||
OffsetOut.ar(\out.kr(0), Pan2.ar(sig * volume, \pan.kr(0)));
|
||||
}).add;
|
||||
d.omi = z;
|
||||
);
|
||||
@ -141,52 +103,33 @@ f.vardel = {
|
||||
|
||||
(
|
||||
[
|
||||
'analog', 'waveshape',
|
||||
'fm', 'grain',
|
||||
'additive', 'wavetable',
|
||||
'chord', 'speech',
|
||||
'swarm', 'noise',
|
||||
'particle', 'string',
|
||||
'modal', 'bass',
|
||||
'snare', 'hat'
|
||||
'Panalog', 'Pwaveshape', 'Pfm', 'Pgrain',
|
||||
'Padditive', 'Pwavetable', 'Pchord', 'Pspeech',
|
||||
'Pswarm', 'Pnoise', 'Pparticle', 'Pstring',
|
||||
'Pmodal', 'Pbass', 'Psnare', 'Phat'
|
||||
].do({arg name, index;
|
||||
var synth;
|
||||
synth = SynthDef(name, {
|
||||
arg out,
|
||||
freq=440,
|
||||
attack=0.01,
|
||||
decay=0.3,
|
||||
sustain=0.5,
|
||||
release=1.0,
|
||||
pan=0,
|
||||
speed=1,
|
||||
accelerate=0,
|
||||
amp=1,
|
||||
alt=1,
|
||||
timbre=0.5,
|
||||
harm=0.5,
|
||||
morph=0.5,
|
||||
level=1,
|
||||
gate=1,
|
||||
lpgdecay=0,
|
||||
lpgcolour=0,
|
||||
mode=0;
|
||||
var env = EnvGen.ar(Env.adsr(attack, decay, sustain, release, curve: [2, -4, -4]), doneAction: Done.freeSelf, gate: gate);
|
||||
var sig;
|
||||
freq = max(0, freq * speed * (1 + (accelerate * env)));
|
||||
sig = MiPlaits.ar(
|
||||
pitch: freq.cpsmidi,
|
||||
timbre: timbre,
|
||||
harm: harm,
|
||||
engine: index,
|
||||
morph: morph,
|
||||
level: level,
|
||||
decay: lpgdecay,
|
||||
lpg_colour: lpgcolour,
|
||||
var env = EnvGen.ar(
|
||||
Env.perc(
|
||||
\attack.kr(0.01),
|
||||
\release.kr(1)
|
||||
), doneAction: Done.freeSelf
|
||||
);
|
||||
sig = Pan2.ar(sig[0], pan);
|
||||
sig = sig * env * amp;
|
||||
OffsetOut.ar(out, sig);
|
||||
var sig;
|
||||
sig = MiPlaits.ar(
|
||||
pitch: \freq.kr(400).cpsmidi,
|
||||
timbre: \timbre.kr(0),
|
||||
harm: \harm.kr(0),
|
||||
engine: index,
|
||||
morph: \morph.kr(0),
|
||||
level: \level.kr(1),
|
||||
decay: \lpgdecay.kr(0),
|
||||
lpg_colour: \lpgcolour.kr(0),
|
||||
);
|
||||
sig = Pan2.ar(sig[0], \pan.kr(0));
|
||||
sig = sig * env * \amp.kr(-6.dbamp);
|
||||
OffsetOut.ar(\out.kr(0), sig);
|
||||
}).add;
|
||||
d.put(name, synth);
|
||||
});
|
||||
@ -194,68 +137,91 @@ f.vardel = {
|
||||
|
||||
|
||||
(
|
||||
['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({
|
||||
[
|
||||
'Bcsaw',
|
||||
'Bmorph',
|
||||
'Bsaw_square',
|
||||
'Bsine_triangle',
|
||||
'Bbuzz',
|
||||
'Bsquare_sub',
|
||||
'Bsaw_sub',
|
||||
'Bsquare_sync',
|
||||
'Bsaw_sync',
|
||||
'Bt_saw',
|
||||
'Bt_square',
|
||||
'Bt_triangle',
|
||||
'Bt_sine',
|
||||
'Bt_ring_mod',
|
||||
'Bsaw_swarm',
|
||||
'Bsaw_comb',
|
||||
'Btoy',
|
||||
'Bfilter_lp',
|
||||
'Bfilter_pk',
|
||||
'Bfilter_bp',
|
||||
'Bfilter_hp',
|
||||
'Bvosim',
|
||||
'Bvowel',
|
||||
'Bvowel_fof',
|
||||
'Bharmonics',
|
||||
'Bbfm',
|
||||
'Bfeedback_fm',
|
||||
'Bchaotic_feedback_fm',
|
||||
'Bplucked',
|
||||
'Bbowed',
|
||||
'Bblown',
|
||||
'Bfluted',
|
||||
'Bstruck_bell',
|
||||
'Bstruck_drum',
|
||||
'Bbkick',
|
||||
'Bcymbal',
|
||||
'Bbsnare',
|
||||
'Bbwavetable',
|
||||
'Bwave_map',
|
||||
'Bwave_line',
|
||||
'Bwave_paraphonic',
|
||||
'Bfiltered_noise',
|
||||
'Btwin_peaks_noise',
|
||||
'Bclocked_noise',
|
||||
'Bgranular_cloud',
|
||||
'Bparticle_noise',
|
||||
'Bdigital_modulation',
|
||||
'Bquestion_mark'].do({
|
||||
arg name, index;
|
||||
var synth;
|
||||
synth = SynthDef(name, {
|
||||
arg out,
|
||||
freq=440,
|
||||
amp=1,
|
||||
attack=0.01,
|
||||
decay=0.3,
|
||||
sustain=0.5,
|
||||
release=1.0,
|
||||
pan=0,begin=0,
|
||||
end=1,speed=1,
|
||||
accelerate=0,
|
||||
timbre=0.5,
|
||||
color=0.5,
|
||||
ws=0,bits=0,
|
||||
resamp=0,
|
||||
decim=32,
|
||||
gate=1;
|
||||
var sig;
|
||||
var env = EnvGen.ar(Env.adsr(attack, decay, sustain, release, curve: [2, -4, -4]), doneAction: Done.freeSelf, gate: gate);
|
||||
freq = max(0, freq * speed * (1 + (accelerate * env)));
|
||||
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 * env * amp, pan));
|
||||
var env = EnvGen.ar(Env.perc(\attack.kr(0.01), \release.kr(1)), doneAction: Done.freeSelf);
|
||||
var freq = \freq.kr;
|
||||
sig = MiBraids.ar(
|
||||
pitch: freq.cpsmidi,
|
||||
timbre: \timbre.kr(0),
|
||||
color: \color.kr(0),
|
||||
resamp: 0,
|
||||
decim: \decim.kr(32),
|
||||
model: index,
|
||||
ws: \ws.kr(0),
|
||||
bits: \bits.kr(0)
|
||||
);
|
||||
OffsetOut.ar(\out.kr(0), Pan2.ar(sig * env * \amp.kr(-6.dbamp), \pan.kr(0)));
|
||||
}).add;
|
||||
d.put(name, synth);
|
||||
});
|
||||
);
|
||||
|
||||
(
|
||||
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,
|
||||
z = SynthDef(\tides, {
|
||||
var env = Env.perc(\attack.kr(0.01), \release.kr(1)).ar(2);
|
||||
var sig = MiTides.ar(
|
||||
freq: \freq.kr(400),
|
||||
shape: \shape.kr(0),
|
||||
slope: \slope.kr(0),
|
||||
smooth: \smooth.kr(0),
|
||||
shift: \shift.kr(0),
|
||||
output_mode: \mode.kr(2),
|
||||
ramp_mode: 1,
|
||||
rate: 1
|
||||
);
|
||||
Out.ar(out, Pan2.ar(sig * volume, pan));
|
||||
OffsetOut.ar(\out.kr(0), Pan2.ar(sig * env * \amp.kr(-6.dbamp), \pan.kr(0)));
|
||||
}).add;
|
||||
d.tides = z;
|
||||
);
|
||||
|
||||
135
Classes/Controllers/MIDIMix.sc
Normal file
135
Classes/Controllers/MIDIMix.sc
Normal file
@ -0,0 +1,135 @@
|
||||
ControllerValue {
|
||||
|
||||
/*
|
||||
* A ControllerValue represents a MIDI Controller value.
|
||||
* It has a minimum and maximum value, and a curve. This
|
||||
* is used to convert from the MIDI value to a value that
|
||||
* is considered usable by the user.
|
||||
*
|
||||
* The curve is similar to the one used by the Env object.
|
||||
*/
|
||||
|
||||
var <>min = 0;
|
||||
var <>max = 1;
|
||||
var <>curve = 0;
|
||||
var <>currentValue;
|
||||
var <>bipolar = false;
|
||||
|
||||
*new {
|
||||
arg min, max, curve;
|
||||
^super.new.init()
|
||||
}
|
||||
|
||||
init {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.curve = curve;
|
||||
this.currentValue = Bus.control;
|
||||
this.bipolar = false;
|
||||
}
|
||||
|
||||
set {
|
||||
arg value;
|
||||
// If bipolar is true, then the value must go from -1 to 1
|
||||
var conversion = value.lincurve(
|
||||
inMin: 0,
|
||||
inMax: 127,
|
||||
outMin: this.min.neg,
|
||||
outMax: this.max,
|
||||
curve: this.curve
|
||||
);
|
||||
this.currentValue.set(conversion);
|
||||
^this.currentValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
MIDIControl {
|
||||
|
||||
/*
|
||||
* This is my personal MIDI controller interface. I am using a
|
||||
* MIDIMix. It has 8 faders, 24 knobs, and 16 buttons. I am only
|
||||
* using the knobs and faders. Two buttons are used to change "bank"
|
||||
* (increments the CC number value).
|
||||
*/
|
||||
|
||||
var <>currentBank = 0;
|
||||
var <>values;
|
||||
|
||||
*new {
|
||||
^super.new.init()
|
||||
}
|
||||
|
||||
init {
|
||||
this.values = IdentityDictionary.new();
|
||||
this.connect(); this.installCallbacks();
|
||||
}
|
||||
|
||||
getInit {
|
||||
arg number;
|
||||
if (this.values[number] == nil) {
|
||||
this.values[number] = ControllerValue.new(
|
||||
min: 0, max: 127, curve: 0
|
||||
);
|
||||
^this.values[number]
|
||||
} {
|
||||
^this.values[number]
|
||||
}
|
||||
}
|
||||
|
||||
setCurve {
|
||||
arg number, curve;
|
||||
this.getInit(number).curve = curve;
|
||||
}
|
||||
|
||||
setBounds {
|
||||
arg number, min, max;
|
||||
var controller = this.getInit(number);
|
||||
controller.min = min;
|
||||
controller.max = max;
|
||||
}
|
||||
|
||||
at {
|
||||
arg number;
|
||||
var control = this.getInit(number);
|
||||
var choices = (
|
||||
value: this.getInit(number).currentValue.getSynchronous,
|
||||
bus: this.getInit(number).currentValue,
|
||||
map: this.getInit(number).currentValue.asMap,
|
||||
kr: In.kr(this.getInit(number).currentValue),
|
||||
);
|
||||
^choices
|
||||
}
|
||||
|
||||
connect {
|
||||
MIDIClient.init;
|
||||
MIDIIn.connectAll(verbose: true);
|
||||
}
|
||||
|
||||
installCallbacks {
|
||||
MIDIIn.addFuncTo(\control, {
|
||||
arg src, chan, num, val;
|
||||
("CONTROL:" + (num + (this.currentBank * 24)) + "=>" + val).postln;
|
||||
this.getInit(num + (this.currentBank * 24)).set(val);
|
||||
});
|
||||
MIDIIn.addFuncTo(\noteOn, {
|
||||
arg src, chan, num, val;
|
||||
"Changing bank".postln;
|
||||
if (chan == 8 && num == 22) {
|
||||
if (this.currentBank > 0) {
|
||||
this.currentBank = this.currentBank - 1;
|
||||
};
|
||||
this.currentBank.postln;
|
||||
};
|
||||
if (chan == 8 && num == 24) {
|
||||
if (this.currentBank < 3) {
|
||||
this.currentBank = this.currentBank + 1;
|
||||
};
|
||||
this.currentBank.postln;
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
50
Classes/EventShortener.sc
Normal file
50
Classes/EventShortener.sc
Normal file
@ -0,0 +1,50 @@
|
||||
EventShortener {
|
||||
|
||||
*findShortcuts {
|
||||
arg pattern;
|
||||
var short, correctedPattern;
|
||||
correctedPattern = List.new();
|
||||
short = Dictionary.newFrom([
|
||||
// Instrument
|
||||
\i, \instrument,
|
||||
// Notes
|
||||
\n, \note,
|
||||
\mn, \midinote,
|
||||
\vel, \velocity,
|
||||
\deg, \degree,
|
||||
\off, \timingOffset,
|
||||
\o, \octave,
|
||||
\f, \freq,
|
||||
\det, \detune,
|
||||
// Durations
|
||||
\d, \dur,
|
||||
\l, \legato,
|
||||
// Amplitude
|
||||
\p, \pan,
|
||||
// Envelope
|
||||
\a, \attack,
|
||||
\d, \decay,
|
||||
\s, \sustain,
|
||||
\r, \release,
|
||||
// Filter control
|
||||
\r, \resonance,
|
||||
\ff, \ffreq,
|
||||
// Modulation
|
||||
\m, \mod,
|
||||
\mo, \midout,
|
||||
\c, \midichan,
|
||||
\st, \stretch,
|
||||
\rt, \root,
|
||||
\scl, \scale,
|
||||
]);
|
||||
|
||||
// shortcuts are turned into regular keys;
|
||||
pattern.do({| element |
|
||||
if (short.includesKey(element),
|
||||
{correctedPattern.add(short[element])},
|
||||
{correctedPattern.add(element)}
|
||||
);
|
||||
});
|
||||
^correctedPattern;
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
FScope {
|
||||
|
||||
*new {
|
||||
^Server.default.freqscope.window.alwaysOnTop_(true);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,3 +1,43 @@
|
||||
Scope {
|
||||
|
||||
*new {
|
||||
^Server.default.scope.window.alwaysOnTop_(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Meter {
|
||||
|
||||
*new {
|
||||
var window = Window.new(
|
||||
"Meter",
|
||||
Rect.new(left: 0, top: 0, width: 680, height: 250),
|
||||
resizable: false,
|
||||
border: true,
|
||||
scroll: false
|
||||
);
|
||||
var meters = ServerMeterView.new(
|
||||
Server.default, window,
|
||||
0@0, 16, 16
|
||||
);
|
||||
window.front;
|
||||
window.alwaysOnTop = true;
|
||||
^window
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
FScope {
|
||||
|
||||
*new {
|
||||
^Server.default.freqscope.window.alwaysOnTop_(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Gui {
|
||||
|
||||
*new {
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
Scope {
|
||||
|
||||
*new {
|
||||
^Server.default.scope.window.alwaysOnTop_(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Meter {
|
||||
|
||||
*new {
|
||||
var window = Window.new(
|
||||
"Meter",
|
||||
Rect.new(left: 0, top: 0, width: 680, height: 250),
|
||||
resizable: false,
|
||||
border: true,
|
||||
scroll: false
|
||||
);
|
||||
var meters = ServerMeterView.new(
|
||||
Server.default, window,
|
||||
0@0, 16, 16
|
||||
);
|
||||
window.front;
|
||||
window.alwaysOnTop = true;
|
||||
^window
|
||||
}
|
||||
|
||||
}
|
||||
30
Classes/Patterns/PXo.sc
Normal file
30
Classes/Patterns/PXo.sc
Normal file
@ -0,0 +1,30 @@
|
||||
Pxo {
|
||||
*new {
|
||||
arg expression, divisor=1, repeats=inf;
|
||||
var xoExp = Array.new(maxSize: expression.size);
|
||||
expression.do({
|
||||
arg char, i;
|
||||
if (char == $x, {xoExp.add(1, i)}, {xoExp.add(Rest(), i)})
|
||||
});
|
||||
xoExp = xoExp.collect({arg item; item / divisor});
|
||||
^Pseq.new(xoExp, repeats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ptx {
|
||||
*new {
|
||||
arg expression, repeats=inf;
|
||||
var xoExp = Array.new(maxSize: expression.size);
|
||||
expression.do({
|
||||
arg char, i;
|
||||
switch(char)
|
||||
{$@} {xoExp.add(2, i)}
|
||||
{$O} {xoExp.add(1, i)}
|
||||
{$o} {xoExp.add(0.5, i)}
|
||||
{$°} {xoExp.add(0.25, i)}
|
||||
{} {xoExp.add(Rest(), i)};
|
||||
});
|
||||
^Pseq.new(xoExp, repeats)
|
||||
}
|
||||
}
|
||||
12
Classes/Patterns/PwrapSeq.sc
Normal file
12
Classes/Patterns/PwrapSeq.sc
Normal file
@ -0,0 +1,12 @@
|
||||
/* This one is taken from Mads Kjeldgaard's */
|
||||
/* https://github.com/madskjeldgaard/Monolithic/blob/main/Classes/Pattern/PwrapSeq.sc */
|
||||
PwrapSeq{
|
||||
*new{
|
||||
arg array, maxIndex, startIndex=0, repeats=inf;
|
||||
|
||||
var indexPat = Pseries.new(startIndex, 1, length: inf) % (maxIndex+1);
|
||||
|
||||
^Pindex.new(listPat: array, indexPat: indexPat, repeats: repeats)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user