gtr/gtr.scd

307 lines
8.8 KiB
Plaintext

////////////////////////////////////////////////////
/* GRANULATING SAMPLER INSTRUMENT //////////////////
////////////////////////////////////rc@kiben.net////
////////////////////////////////////////////////////
| .-.
| / \ .-.
| / \ / \ .-. .-. _
+--/-------\-----/-----\-----/---\---/---\---/-\-
| / \ / \ / '-' '-'
|/ '-' '-'
Ljudmila OTF Hackathon, Maribor 1-6 March 2022 */
////////////////////////////////////////////
// guitar MAC address 98:CD:AC:63:78:E2
// RUNME 0 =========================================
s.boot();
// RUNME 1 =========================================
// -------------------------------------------------
( // SETUP ----------------------------------------- -
// ---------------------------------------------------
// Allocate a 4 second mono buffer
b = Buffer.alloc(s, s.sampleRate * 4.0, 1);
// load a test file
f = Buffer.read(s, thisProcess.nowExecutingPath.dirname
+/+ "sounds/Front_Left.wav");
// Open port 57121 for ESP32 UDP OSC
thisProcess.openUDPPort(57121);
);
// RUNME 2 ==========================================
// -------------------------------------------------
( // DEFINE SYNTHS --------------------------------- <--
// -------------------------------------------------
( // direct signal + reverb -------------------------
SynthDef("dryIn", { arg in=0, out=0;
var signal, dry, wet;
dry = SoundIn.ar(in);
wet = FreeVerb.ar(dry, mix:0.4, room:0.55, damp:0);
signal = Pan2.ar(wet, 0);
signal = signal * 0.9;
Out.ar(0, signal);
}).add;
);
( // mono buffer recorder ----------------------------
// with loop and overdub modes /////////////////////
// make record togglable between looping, direct or onset detection trigger
SynthDef("recBuf",{ arg in=0, out=0, bufnum=0, t_trig=0, l=0, overdub=0;
var sig, chain, onsets;
sig = SoundIn.ar(in);
// Onsets
chain = FFT(LocalBuf(512), sig);
onsets = Onsets.kr(chain, MouseX.kr(0,1), \rcomplex);
RecordBuf.ar(sig, bufnum, loop:l,
preLevel: overdub,
doneAction: 0, trigger:t_trig,);
}).add;
);
// ----------------------------------------------------
( // Granulator --------------------------------------
// ----------------------------------------------------
// a custom envelope
//var winenv;
//winenv = Env([0, 1, 0], [0.5, 0.5], [8, -8]);
//z = Buffer.sendCollection(s, winenv.discretize, 1);
// ~rndpos = LFNoise2.kr(0.1).range(0, 1);
SynthDef(\buf_grain, { | out, gate = 1, amp = 1,
sndbuf, envbuf, pan=0, imp=50,
pitchmodeindex=0, sensorpitch=1,
positionmodeindex=0, sensorposition=0,
impulsemodeindex=0, sensorimpulse=0,
rlow= -1, rhigh=1 |
var signal, env, freqdev, pos,
pitchmode0, pitchmode1, pitch,
positionmode0, positionmode1, position,
impulsemode0, impulsemode1, impulse;
// grain pitch mode -untransposed, random, or sensor controlled
pitchmode0 = 1;
pitchmode1 = LFNoise1.kr.range(rlow, rhigh);
pitch = Select.kr(pitchmodeindex,
[pitchmode0, pitchmode1, sensorpitch]);
// granular playhead mode - fixed random or sensor controlled
positionmode0 = 1;
positionmode1 = LFNoise1.kr.range(0, 1);
position = Select.kr(positionmodeindex,
[positionmode0, positionmode1, sensorposition]);
// grain impulse frequency mode - random, metric or sensor based impulse modes
impulsemode0 = Impulse.kr(imp);
impulsemode1 = Dust.kr(imp);
impulse = Select.kr(impulsemodeindex,
[impulsemode0, impulsemode1, sensorimpulse]);
env = EnvGen.kr(
Env([0, 1, 0], [1, 1], \sin, 1), gate, levelScale: amp, doneAction: 2);
signal = GrainBuf.ar(2,
impulse, // selectable between impulse.kr and dust.kr
0.1, sndbuf, pitch, position, 2, pan, envbuf);
signal = FreeVerb2.ar(signal[0], signal[1],
mix:0.4, room:0.5, damp:0
);
signal = signal* env;
Out.ar(0,signal);
}).add;
);
)
// RUNME 3 ==========================================
// ----------------------------------------------------
(( // START SYNTHS ---------------------------------
// ----------------------------------------------------
r = Synth(\recBuf, [\in, 0, \out, 0, \bufnum, b, \t_trig, 0]); // recorder
~granulator1 = Synth(\buf_grain, [\sndbuf, b, \envbuf, -1]); // granulate
~gtrIn = Synth(\dryIn); // dry audio signaL
));
~gtrIn.free;
// RUNME 4 ==========================================
// ----------------------------------------------------
(( // OSC Receivers // ENABLE SENSOR AND SWITCH VALUES <--
// ----------------------------------------------------
~pitchmode = 0; ~positionmode = 2; ~impulsemode = 0;
( // accel gyro quaternion mapping ///////////////////
// msg[1] msg[2] msg[3] X Y Z ==> ROLL, PITCH, YAW
o = OSCdef(\test, { arg msg, time, addr, recvPort, rlow, rhigh;
// PAN ------- X Roll
~granulator1.set(\pan, msg[1].linlin(-0.3, 0.3, -1, 1));
// PITCH ------- Y Pitch
~granulator1.set(\sensorpitch, msg[3].linlin(-1, 1, 0, 4));
~granulator1.set(\pitchmodeindex, ~pitchmode );
// POSITION ------- Z Yaw
~granulator1.set(\sensorposition, msg[2].linlin(-1, 1, 0, 4));
~granulator1.set(\positionmodeindex, ~positionmode );
// RATE ------- X (roll [with PAN])
~granulator1.set(\sensorimpulse, msg[2].linlin(-1, 1, 5, 50));
~granulator1.set(\impulsemodeindex, ~impulsemode );
//msg.postln;
}; , '/euler');
);
// ----------------------------------------------------
// button press mapping ///////////////////////////////
// ----------------------------------------------------
p = OSCdef(\keys, { arg msg, time, addr, recvPort;
//msg.postln;
// BUTTON 0 + 3 ----> ZERO EULER / MPU6050
if (msg[9] == 1 && msg[10] == 1,
{ " ===== EULER ZEROED! =====".postln },
{});
if (msg[9] == 1,
{ r.set( \in, 0, \l, 0, \t_trig, 1);
" /////////// SAMPLING!".postln },
{});
if (msg[10] == 1,
{
" /////////// SOOOOOOMMMEEETHIIIINNGGGG!".postln },
{});
if (msg[11] == 1,
{
" /////////// ////////////////////////////!".postln },
{});
if (msg[12] == 1,
{
"=========================================".postln },
{});
// TOGGLE 1 ----> LOOP RECORDING MODE ON/OFF
/* if (msg[13] == 1,
{ r.set(\l, 1); "LOOPING ON".postln; },
{ r.set(\l, 0); "LOOPING OFF".postln; });
// TOGGLE 2 ----> OVERDUB RECORDING MODE ON/OFF
if (msg[14] == 1,
{ r.set(\overdub, 1); "OVERDUB ON".postln; },
{ r.set(\overdub, 0); "OVERDUB OFF".postln; },
);*/
/* case
//{ msg[14] == 0} {"result".postln; msg.postln}
// BUTTON 0 && 3 RESET/ZERO SENSORS [in firmware]
// BUTTON 0 ----> RECORD TO BUFFER 0
{ msg[9] == 1 } { r.set( \in, 0, \l, 0, \t_trig, 1);
msg.postln; msg[9].postln; "SAMPLING!".postln }
// BUTTON 0 + 3 ----> ZERO EULER / MPU6050
// TOGGLE O ----> OVERDUB MODE ON/OFF
{ msg[14] == 0 } { r.set(\overdub, 0); "OVERDUB OFF".postln; }
{ msg[14] == 1 } { r.set(\overdub, 1); "OVERDUB ON".postln; }
// TOGGLE 2
//{ msg[13] == 0 } { ~granulator1.set(\positionmodeindex, 1 ); }
//{ msg[13] == 1 } { ~granulator1.set(\positionmodeindex, 2 ); }
// TOGGLE 3 ----> LOOP RECORDING MODE ON/OFF
{ msg[13] == 0 } { "LOOPING OFF".postln; r.set(\l, 0); msg[13].postln;}
{ msg[13] == 1 } { "LOOPING ON! SAMPLING".postln; r.set(\l, 1); msg[13].postln; };*/
} , '/keys');
);
);
// ----------------------------------------------------
// ----------------------------------------------------
// PERFORMABLE PARAMETERS /////////////////////////////
// ----------------------------------------------------
// ----------------------------------------------------
// start recording (without button)
r.set(\in, 0, \l, 0, \t_trig, 1);
// set recorder loop and overdub modes
r.set(\l, 1); // looping record on - MAPPED TO SWITCH 3
r.set(\l, 0); // off
r.set(\overdub, 1); // overdub mode on - MAPPED TO SWITCH 4
r.set(\overdub, 0); // off
/// random pitch/rate low and high values
~granulator1.set(\rlow, 0);
~granulator1.set(\rlow, -10);
~granulator1.set(\rhigh, 1);
~granulator1.set(\rhigh, 10);
~impulsemode = 0; // impulse
~impulsemode = 1; // dust
~impulsemode = 2; // sensor
~pitchmode = 0; // no transpose
~pitchmode = 1; // random
~pitchmode = 2; // sensor (pitch) input
~positionmode = 0; // middle of sample
~positionmode = 1; // random position
~positionmode = 2; // sensor (position) input
// set grain impulse rate
~granulator1.set(\imp, 50);
// fix doneaction
~granulator1.set(\gate, 1); // granulator on
~granulator1.set(\gate, 0); // granulator off
/////////////////////////////////////////////////
// -----------------------------------------------
// -----------------------------------------------
// -----------------------------------------------
// DUMP ALL OSC MESSAGES (for debugging) ////////
OSCFunc.trace(true);
OSCFunc.trace(false);
thisProcess.openPorts; // list all open ports
// -----------------------------------------------
// CODE DUMP ZONE ///////////////////////////////
// switch to the custom env
//~granulator1.set(\envbuf, z);
//~granulator1.set(\envbuf, -1);
//n = NetAddr("127.0.0.1", NetAddr.langPort);
//n = NetAddr.new("224.0.1.9", 6696);