387 lines
11 KiB
Plaintext
387 lines
11 KiB
Plaintext
////////////////////////////////////////////////////
|
|
/* GRANULATING SAMPLER INSTRUMENT //////////////////
|
|
////////////////////////////////////rc@kiben.net////
|
|
////////////////////////////////////////////////////
|
|
|
|
| .-.
|
|
| / \ .-.
|
|
| / \ / \ .-. .-. _
|
|
+--/-------\-----/-----\-----/---\---/---\---/-\-
|
|
| / \ / \ / '-' '-'
|
|
|/ '-' '-'
|
|
|
|
Ljudmila OTF Hackathon, Maribor 1-6 March 2022 */
|
|
// GTR MAC address: 10:97:BD:36:D6:4E
|
|
|
|
// 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;
|
|
);
|
|
|
|
// ---------~positionmode = 1; -------------------------------------------
|
|
( // 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, sensorgdur=0.1, sensorgpan=0,
|
|
positionmodeindex=0, gdurmodeindex=0, gpanmodeindex=0,
|
|
sensorposition=0, impulsemodeindex=0, sensorimpulse=0,
|
|
rlow= -1, rhigh=1 |
|
|
|
|
var signal, env, freqdev, pos,
|
|
pitchmode0, pitchmode1, pitch,
|
|
gdurmode0, gdurmode1, gdurmode2, gdur,
|
|
gpanmode0, gpanmode1, gpan,
|
|
positionmode0, positionmode1, position,
|
|
impulsemode0, impulsemode1, impulse;
|
|
|
|
// grain duration mode -untransposed, random, or sensor controlled
|
|
gdurmode0 = 0.1;
|
|
gdurmode1 = LFNoise1.kr.range(0.2, 3.3);
|
|
gdurmode2 = LFNoise1.kr.range(0.2, 3.3);
|
|
|
|
gdur = Select.kr(gdurmodeindex,
|
|
[gdurmode0, gdurmode1, gdurmode2, sensorgdur]);
|
|
|
|
// grain pan mode -untransposed, random, or sensor controlled
|
|
gpanmode0 = 0.1;
|
|
gpanmode1 = LFNoise1.kr.range(0.1, 10.3);
|
|
gpan = Select.kr(gpanmodeindex,
|
|
[gpanmode0, gpanmode1, sensorgpan]);
|
|
|
|
// 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
|
|
gdur, sndbuf, pitch, position, 2, gpan, 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 = 0; ~impulsemode = 0; ~gdurmode=0; ~gpanmode=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));
|
|
~granulator1.set(\panmodeindex, ~panmode );
|
|
|
|
// 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 );
|
|
|
|
~granulator1.set(\sensorgdur, msg[2].linlin(-1, 1, 0.1, 1));
|
|
~granulator1.set(\gdurmodeindex, ~gdurmode );
|
|
|
|
~granulator1.set(\sensorgpan, msg[2].linlin(-1, 1, -1, 1));
|
|
~granulator1.set(\gpanmodeindex, ~gpanmode );
|
|
|
|
//msg.postln;
|
|
|
|
}; , '/euler');
|
|
);
|
|
|
|
// ----------------------------------------------------
|
|
// button press mapping ///////////////////////////////
|
|
// ----------------------------------------------------
|
|
|
|
~btn0val = 0; ~btn1val = 0; ~btn2val = 0; ~btn3val = 0;
|
|
~btn4val = 0; ~btn5val = 0; ~btn6val = 0; ~btn7val = 0;
|
|
~btn8val = 0; // shift buttons
|
|
|
|
|
|
m = NetAddr("127.0.0.1", 57120); // loopback
|
|
m.sendMsg("/chat", "Hello App 1");
|
|
|
|
|
|
p = OSCdef(\keys, { arg msg, time, addr, recvPort;
|
|
//msg.println;
|
|
// ==============================
|
|
// BUTTON MAPPING
|
|
// ==============================
|
|
|
|
// TRIGGER BUTTONS (3) ------------------------------
|
|
|
|
// if SHIFT key is 0:
|
|
if (msg[9] == 0, {
|
|
|
|
// BUTTON X ----- TRIGGER ONESHOT BUFFER RECORD
|
|
if (msg[10] == 1, { r.set( \in, 0, \l, 0, \t_trig, 1);
|
|
" /////////// SAMPLING!".postln }, {});
|
|
|
|
// BUTTON X ----> LOOP RECORDING MODE ON/OFF
|
|
if (msg[11]==1,
|
|
{
|
|
( ~btn4val = (~btn4val + 1) % 3 ) ;
|
|
switch( ~btn4val,
|
|
0, { r.set(\l, 0); "RECORD LOOPING OFF".postln; },
|
|
1, { r.set(\l, 1); "RECORD LOOPING ON".postln; },
|
|
2, { r.set(\l, 1); "RECORDING ONSET DETECTION ON".postln; }, //todo
|
|
)
|
|
});
|
|
|
|
// BUTTON X ----> OVERDUB RECORDING MODE ON/OFF
|
|
if (msg[12]==1,
|
|
{
|
|
( ~btn2val = (~btn2val + 1) % 2 ) ;
|
|
switch( ~btn2val,
|
|
0, { r.set(\overdub, 0); "SAMPLE OVERDUB OFF".postln; },
|
|
1, { r.set(\overdub, 1); "SAMPLE OVERDUB ON".postln; },
|
|
)
|
|
});
|
|
|
|
}, /// SHIFT 0 LOGIC ENDS HERE
|
|
|
|
{ // SHIFT IN STATE 1 =======================
|
|
|
|
// BUTTON X ----- GRAIN DURATION MODE
|
|
if (msg[15]==1,
|
|
{
|
|
( ~btn8val = (~btn8val + 1) % 4 ) ;
|
|
switch(~btn8val,
|
|
0, { ~gdurmode = 0; "DURATION MODE 0".postln; },
|
|
1, { ~gdurmode = 1; "DURATION MODE 1".postln; },
|
|
2, { ~gdurmode = 2; "DURATION MODE 2".postln; },
|
|
3, { ~gdurmode = 3; "DURATION MODE 3".postln; },
|
|
)
|
|
});
|
|
|
|
// BUTTON X ----- GRANULAR POSITION MODE
|
|
if (msg[13]==1,
|
|
{
|
|
( ~btn3val = (~btn3val + 1) % 3 ) ;
|
|
switch(~btn3val,
|
|
0, { ~positionmode = 0; "POSITION MODE FIXED".postln; },
|
|
1, { ~positionmode = 1; "POSITION MODE RANDOM".postln; },
|
|
2, { ~positionmode = 2; "POSITION MODE SENSOR".postln; },
|
|
)
|
|
});
|
|
|
|
// BUTTON X ----- GRANULAR PITCH MODE
|
|
if (msg[14]==1,
|
|
{
|
|
( ~btn6val = (~btn6val + 1) % 3 ) ;
|
|
switch(~btn6val,
|
|
0, { ~pitchmode = 0; "PITCH MODE FIXED".postln; },
|
|
1, { ~pitchmode = 1; "PITCH MODE RANDOM".postln; },
|
|
2, { ~pitchmode = 2; "PITCH MODE SENSOR".postln; },
|
|
)
|
|
});
|
|
|
|
// BUTTON X ----- GRANULAR IMPULSE MODE
|
|
if (msg[16]==1,
|
|
{
|
|
( ~btn7val = (~btn7val + 1) % 3 ) ;
|
|
switch( ~btn7val,
|
|
0, { ~granulator1.set(\impulsemodeindex, 0 ); "IMPULSE MODE FIXED".postln; },
|
|
1, { ~granulator1.set(\impulsemodeindex, 1 ); "IMPULSE MODE DUST".postln; },
|
|
2, { ~granulator1.set(\impulsemodeindex, 2 ); "IMPULSE MODE SENSOR".postln; },
|
|
)
|
|
});
|
|
|
|
|
|
// BUTTON X && X RESET/ZERO SENSORS [in firmware just here for notificaton]
|
|
if (msg[12] == 1, { " ===== EULER ZEROED! =====".postln }, {});
|
|
|
|
// GTR INPUT =======================
|
|
if (msg[11]==1,
|
|
{
|
|
( ~btn2val = (~btn2val + 1) % 3 ) ;
|
|
switch(~btn2val,
|
|
0, { ~gtrIn.set(\in, 1 ); "DRY SIGNAL OFF".postln; },
|
|
1, { ~gtrIn.set(\in, 0 ); "DRY SIGNAL ON".postln; },
|
|
2, { ~gtrIn.set(\in, 1 ); "DRY + REVERB ON".postln; },
|
|
)
|
|
});
|
|
|
|
} // SHIFT ONE LOGIC ENDS HERE ================
|
|
|
|
); /// closes SHIFT 1
|
|
|
|
} , '/keys');
|
|
|
|
);
|
|
);
|
|
GUI
|
|
// ----------------------------------------------------
|
|
// ----------------------------------------------------
|
|
// 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, -1);
|
|
~granulator1.set(\rhigh, 1);
|
|
~granulator1.set(\rhigh, 2);
|
|
|
|
~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
|
|
|
|
~gdurmode = 0 ; // random position
|
|
~gdurmode = 1 ; // random position
|
|
~gdurmode = 2 ; // random position
|
|
|
|
~gpanmode = 0 ; // random position
|
|
~gpanmode = 1 ; // random position
|
|
~gpanmode = 2 ; // random position
|
|
|
|
// 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);
|
|
|
|
|