010 Moving Mountains
Published on: 2020-03-15
Description
Following the flow of kinesthetic experience, navigating the structures of the body and using the impact of the sound to inspire movement and imagery.
The sound is a combination of granulated cello and vocal recordings, as well as a heavily filtered kick drum sample.
Source Code
Requires KF Supercollider-quarks and movement sensors. We use MiniBees, but with a bit of rewriting the MiniBeeUtils should work with any sensor data. See the full gitlab repo for more details on implementation.
(
// define global variables
~numSpeakers = 2;
~masterBus = 0;
~root = "/path/to/your/project/root";
~sketchdir = ~root+/+"sketches";
~mb = (9..16); // ids of minibees
~play = Dictionary.new();
~free = Dictionary.new();
~stop = Dictionary.new();
// load in buffers, one dictionary entry per directory in the audio
// directory. These can be found in the gitlab repo.
~buf = Dictionary.new;
PathName((~root+/+"audio").standardizePath).folders.do({|folder|
s.makeBundle(nil, {
~buf.add(
folder.folderName.asSymbol -> folder.entries.collect({|file|
Buffer.readChannel(s, file.fullPath, channels: 0);
})
);
});
});
// set up MIDI, in this case a Launchpad controller
MIDIClient.init;
MIDIClient.sources.do{|device, idx|
if(device.name.contains("Launchpad MIDI 1")){
MIDIIn.connect(idx, device);
"% connected\n".postf(device.name);
~launchPadOut = MIDIOut.newByName(
"Launchpad",
"Launchpad MIDI 1"
);
~hasLaunchPad = true;
~launchPadOut.control(176, 0, 127);
~launchPadOut.latency = 0;
}
};
// some basic colors for the Launchpad
~launchPadColor = (
\off: 12,
\redLo: 13,
\redHi: 15,
\amberLo: 29,
\amberHi: 63,
\yellow: 62,
\greenLo: 28,
\greenHi: 60
);
// Evaluate the necessary SynthDefs:
SynthDef(\route, {
var sig, env;
env = EnvGen.kr(
Env.asr(
\attack.kr(0.1), 1.0,
\release.kr(0.1)
),
gate: \gate.kr(1),
doneAction: \da.kr(2)
);
sig = In.ar(\in.kr(~numSpeakers), ~numSpeakers);
sig = sig * env * \amp.kr(1, 0.1);
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\pm, {
var sig, env, freq, modenv, mod;
freq = \freq.kr(440);
modenv = EnvGen.kr(
Env.asr(
\modattack.kr(0.1), 1.0,
\modrelease.kr(0.1)
),
gate: \gate.kr(1)
);
mod = modenv * \pmindex.kr(0);
env = EnvGen.kr(
Env.asr(
\attack.kr(0.1), 1.0,
\release.kr(0.1)
),
gate: \gate.kr(1),
doneAction: \da.kr(2)
);
sig = PMOsc.ar(freq, \modfreq.kr(440), mod);
sig = sig * AmpCompA.kr(freq);
sig = sig * env * \amp.kr(0.3, 0.1);
sig = PanAz.ar(~numSpeakers, sig, \pan.kr(0), width: \width.kr(2));
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\flanger, {
var in, sig, env, maxdelay, maxrate, dsig, mixed, mix, local;
env = EnvGen.kr(
Env.asr(
\attack.kr(0.01), 1,
\release.kr(1)
),
gate: \gate.kr(1),
doneAction: \da.kr(2)
);
mix = \mix.kr(1);
maxdelay = 0.013;
maxrate = 10.0;
in = In.ar(\in.kr((~numSpeakers + ~numSubs), ~numSpeakers));
local = LocalIn.ar(~numSpeakers);
dsig = AllpassL.ar(
in + (local * \feedback.kr(0.0)),
maxdelay * 2,
LFPar.kr(
\rate.kr(0.06) * maxrate,
0,
\depth.kr(0.08) * maxdelay,
\delay.kr(0.1) * maxdelay
),
\decay.kr(0.0)
);
mixed = in + dsig;
LocalOut.ar(mixed);
sig = (1 - mix) * in + (mixed * mix);
sig = sig * env * \amp.kr(1);
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\jpverb, {
var source, sig, env, mix;
mix = \mix.kr(1);
env = EnvGen.kr(
Env.asr(
\attack.kr(0.01), 1,
\release.kr(1)
),
gate: \gate.kr(1),
doneAction: \da.kr(2)
);
source = In.ar(\in.kr(~numSpeakers), ~numSpeakers);
source = source.sum * env;
sig = JPverb.ar(
source,
\revtime.kr(1),
\damp.kr(0),
\size.kr(1),
\early.kr(0.707)
);
sig = (1 - mix) * source + (sig * mix);
sig = SplayAz.ar(~numSpeakers, sig, spread: 0.5, width:~numSpeakers);
Out.ar(\out.kr(0), sig);
}).add;
SynthDef(\eq, {
arg in, attack=0.1, release=0.1, amp=1, out=0, gate=1, da=2,
locut=20, loshelffreq=200, loshelfdb=0,
hishelffreq=1500, hishelfdb=0, hicut=20000,
peakfreq=600, peakrq=1, peakdb=0;
var sig, env;
env = EnvGen.kr(
Env.asr(attack, 1, release),
gate: gate,
doneAction: da
);
sig = In.ar(in, ~numSpeakers);
sig = BLowShelf.ar(sig, loshelffreq, db: loshelfdb);
sig = BHiShelf.ar(sig, hishelffreq, db: hishelfdb);
sig = BHiPass.ar(sig, locut);
sig = BLowPass.ar(sig, hicut);
sig = BPeakEQ.ar(sig, peakfreq, peakrq, peakdb);
sig = sig * amp * env;
Out.ar(out, sig);
}).add;
SynthDef(\grbufphasor, {
var sig, env, pos, posDev, buf, duration, trig, rate,
rateDev, startPos, endPos, pan, panDev, playbackRate;
buf = \buf.kr(0);
playbackRate = \playbackRate.kr(1);
startPos = \startPos.kr(0);
endPos = \endPos.kr(1);
duration = (endPos - startPos).abs * (
BufFrames.kr(buf) / SampleRate.ir()
);
env = EnvGen.kr(
Env.asr(
\attack.kr(0.01), 1,
\release.kr(1)
),
gate: \gate.kr(1),
doneAction: \da.kr(2)
);
trig = Impulse.kr(\grainfreq.kr(10));
posDev = \posDev.kr(0);
pos = Line.kr(
startPos,
endPos, (duration * playbackRate.reciprocal)
);
pos = (pos + TRand.kr(0.0, posDev, trig)).mod(endPos);
rate = \rate.kr(1);
rateDev = \rateDev.kr(0);
rate = rate + TRand.kr(0.0, rateDev, trig);
pan = \pan.kr(0);
panDev = \panDev.kr(0);
pan = pan + TRand.kr(0.0, panDev, trig);
pan = pan.mod(1.0);
sig = GrainBuf.ar(
~numSpeakers,
trig,
\grainsize.kr(0.2),
buf,
rate,
pos,
pan: pan
);
sig = sig * env * \amp.kr(0.3, 0.1);
Out.ar(\out.kr(0), sig);
}).add;
)