Explorar el Código

Merge branch 'sc_cleaned'

merged SC part with the rest
Thomas GUFFROY hace 6 meses
padre
commit
69d2b16ce1

+ 4 - 1
SC/1_environment_setup.scd

@@ -18,4 +18,7 @@ s.waitForBoot({
         sig!2  // Stereo output
     }.play;
 });
-)
+)
+
+
+//Server.killAll

+ 0 - 45
SC/2_oscillator_synthdefs.scd

@@ -1,45 +0,0 @@
-// Basic oscillator SynthDefs
-(
-// Pure sine tone
-SynthDef(\sineTone, { |out=0, freq=440, amp=0.1, pan=0, attack=0.01, release=1|
-    var sig, env;
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-    sig = SinOsc.ar(freq) * env * amp;
-    Out.ar(out, Pan2.ar(sig, pan));
-}).add;
-
-// Square wave tone
-SynthDef(\squareTone, { |out=0, freq=440, amp=0.1, pan=0, attack=0.01, release=1, width=0.5|
-    var sig, env;
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-    sig = Pulse.ar(freq, width) * env * amp;
-    Out.ar(out, Pan2.ar(sig, pan));
-}).add;
-
-// Sawtooth wave tone
-SynthDef(\sawTone, { |out=0, freq=440, amp=0.1, pan=0, attack=0.01, release=1|
-    var sig, env;
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-    sig = Saw.ar(freq) * env * amp;
-    Out.ar(out, Pan2.ar(sig, pan));
-}).add;
-
-// Triangle wave tone
-SynthDef(\triTone, { |out=0, freq=440, amp=0.1, pan=0, attack=0.01, release=1|
-    var sig, env;
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-    sig = LFTri.ar(freq) * env * amp;
-    Out.ar(out, Pan2.ar(sig, pan));
-}).add;
-
-// FM synthesis tone
-SynthDef(\fmTone, { |out=0, freq=440, amp=0.1, pan=0, attack=0.01, release=1, modRatio=2, modAmt=0.5|
-    var sig, env, mod;
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-    mod = SinOsc.ar(freq * modRatio, 0, freq * modAmt);
-    sig = SinOsc.ar(freq + mod) * env * amp;
-    Out.ar(out, Pan2.ar(sig, pan));
-}).add;
-
-"Oscillator SynthDefs loaded".postln;
-)

+ 118 - 0
SC/2_synthdefs.scd

@@ -0,0 +1,118 @@
+(
+
+// Define the bus to send the audio to the filter
+~bus = Bus.audio(s, 2);
+~fxBus = Bus.audio(s, 2);
+~synthGroup = Group.head(s);             // synths go here
+~filterGroup = Group.after(~synthGroup); // filter comes after
+
+~lfoBus = Bus.control(s, 1);       // 1-channel control bus for the LFO
+~filterEnvBus = Bus.control(s, 1); // 1-channel control bus for the filter envelope
+
+
+// Low Frequency Oscillator for parameter modulation
+SynthDef(\lfo, { |out=0, freq=2, min=(-0.5), max=0.5, waveform=0|
+    var lfo;
+
+    // Select waveform based on parameter
+    lfo = Select.kr(waveform, [
+        SinOsc.kr(freq),         // Sine wave (waveform=0)
+        LFTri.kr(freq),          // Triangle wave (waveform=1)
+        LFSaw.kr(freq, 0, -1),   // Decreasing sawtooth wave (waveform=2)
+        LFPulse.kr(freq, 0, 0.5) // Square wave (waveform=3)
+    ]);
+
+    // Scale to range
+    lfo = lfo.range(min, max);
+
+    // Output to control bus
+    Out.kr(out, lfo);
+}).add;
+
+
+
+// RGB-controlled synthesizer with amplitude envelope
+SynthDef(\rgbSynth, { |out=0, freq=440, amp=1, ampAttack=0.01, ampRelease=1,
+	pitchAttack=0, pitchDecay=0, pitchRatio=1,
+	redAmt=1, greenAmt=1, blueAmt=1,
+	lfoBus=(-1), lfoDepth=0|
+
+    var env, gate, pitchEnv, red, green, blue, sig, modFreq, lfo;
+
+	gate = \gate.kr(0);
+
+    // Amplitude envelope
+    env = EnvGen.kr(Env.adsr(ampAttack, 0, 1, ampRelease), gate);
+
+    // Pitch envelope
+    pitchEnv = EnvGen.kr(Env.adsr(pitchAttack, pitchDecay, 0, pitchDecay), gate);
+
+	 // If lfoBus < 0, read from bus 0 (assumed silent)
+	lfo = In.kr(lfoBus.max(0));
+	lfo.postln();
+
+    // Calculate modulated frequency
+    modFreq = freq * (1 + (pitchEnv * (pitchRatio - 1))) * (1 + (lfo * lfoDepth));
+
+    // Different waveforms for RGB components
+    red = SinOsc.ar(modFreq) * redAmt;
+    green = Saw.ar(modFreq) * greenAmt;
+    blue = Pulse.ar(modFreq, 0.5) * blueAmt;
+
+    // Mix the waveforms
+    sig = (red + green + blue) / 3;
+
+    // Apply envelope and output
+    sig = sig * env * amp;
+    Out.ar(out, sig!2);
+}).add;
+
+
+SynthDef(\filterEnv, {
+    |out=0, gate=1, attack=0.001, decay=0|
+
+    var env = EnvGen.kr(Env.adsr(attack, decay, 0, decay), gate);
+    Out.kr(out, env);
+}).add;
+
+
+// The sound goes into a LPF
+SynthDef(\lpf, { |in=0, out=0, cutoff=18000, resonance=1,
+	lfoBus=(-1), lfoDepth=0, envBus=(-1), envDepth=0|
+
+	var sig, lfo, env, modCutoff, rq;
+
+	// Read audio and control signals from buses
+    sig = In.ar(in, 2);
+    lfo = In.kr(lfoBus.max(0));
+    env = In.kr(envBus.max(0));
+
+	modCutoff = cutoff * (1 + (lfo * lfoDepth)) * (1 + (env * envDepth));
+	modCutoff = modCutoff.clip(20, 18000);  // safety
+
+	rq = resonance.linexp(0, 1, 1, 0.07); // Transforms resonance amount to rq with exp interpolation
+
+    sig = RLPF.ar(sig, modCutoff, rq); // low-pass filter
+
+    Out.ar(out, sig);
+}).add;
+
+
+
+// Create a SynthDef with the VSTPlugin UGen
+SynthDef(\juceVST, { |in, out|
+
+	var sound = In.ar(in, 2);
+	ReplaceOut.ar(out, VSTPlugin.ar(sound, 2))
+
+}).add;
+
+
+
+"RGB-controlled synthesizer loaded".postln;
+)
+
+
+
+
+

+ 0 - 81
SC/2b_rgb_synthdefs.scd

@@ -1,81 +0,0 @@
-(
-// RGB-controlled synthesizer with amplitude envelope
-SynthDef(\rgbSynth, { |out=0, freq=440, amp=0.5, attack=0.01, release=1, redAmt=0.5, greenAmt=0.5, blueAmt=0.5|
-    var env, red, green, blue, sig;
-
-    // Amplitude envelope
-    env = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-
-    // Different waveforms for RGB components
-    red = SinOsc.ar(freq) * redAmt;
-    green = Saw.ar(freq) * greenAmt;
-    blue = Pulse.ar(freq, 0.5) * blueAmt;
-
-    // Mix the waveforms
-    sig = (red + green + blue) / 3;
-
-    // Apply envelope and output
-    sig = sig * env * amp;
-    Out.ar(out, sig!2);
-}).add;
-
-// RGB-controlled synthesizer with filter envelope
-SynthDef(\rgbFilterSynth, { |out=0, freq=440, amp=0.5, attack=0.01, release=1,
-    filterAttack=0.01, filterRelease=1, filterMin=200, filterMax=5000,
-    redAmt=0.5, greenAmt=0.5, blueAmt=0.5|
-
-    var ampEnv, filterEnv, red, green, blue, sig;
-
-    // Amplitude envelope
-    ampEnv = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-
-    // Filter envelope
-    filterEnv = EnvGen.kr(Env.perc(filterAttack, filterRelease));
-
-    // Different waveforms for RGB components
-    red = SinOsc.ar(freq) * redAmt;
-    green = Saw.ar(freq) * greenAmt;
-    blue = Pulse.ar(freq, 0.5) * blueAmt;
-
-    // Mix the waveforms
-    sig = (red + green + blue) / 3;
-
-    // Apply filter with envelope control
-    sig = RLPF.ar(sig, filterEnv.linexp(0, 1, filterMin, filterMax), 0.5);
-
-    // Apply amplitude envelope and output
-    sig = sig * ampEnv * amp;
-    Out.ar(out, sig!2);
-}).add;
-
-// RGB-controlled synthesizer with pitch envelope
-SynthDef(\rgbPitchSynth, { |out=0, freq=440, amp=0.5, attack=0.01, release=1,
-    pitchAttack=0.01, pitchRelease=1, pitchRatio=2,
-    redAmt=0.5, greenAmt=0.5, blueAmt=0.5|
-
-    var ampEnv, pitchEnv, red, green, blue, sig;
-
-    // Amplitude envelope
-    ampEnv = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
-
-    // Pitch envelope
-    pitchEnv = EnvGen.kr(Env.perc(pitchAttack, pitchRelease));
-
-    // Calculate modulated frequency
-    freq = freq * (1 + (pitchEnv * (pitchRatio - 1)));
-
-    // Different waveforms for RGB components
-    red = SinOsc.ar(freq) * redAmt;
-    green = Saw.ar(freq) * greenAmt;
-    blue = Pulse.ar(freq, 0.5) * blueAmt;
-
-    // Mix the waveforms
-    sig = (red + green + blue) / 3;
-
-    // Apply amplitude envelope and output
-    sig = sig * ampEnv * amp;
-    Out.ar(out, sig!2);
-}).add;
-
-"RGB-controlled synthesizers loaded".postln;
-)

+ 61 - 0
SC/3_effects_integration.scd

@@ -0,0 +1,61 @@
+(
+//PUT HERE THE NUMBER OF POLYPHONY VOICES
+var nbVoices = 16;
+
+//PUT HERE THE PATH TO THE JUCE VST3 PLUGIN
+var vst3Path = "Users/thomas/Desktop/MOscilloscope.vst3";
+
+
+// LFO Synth
+~lfo = Synth(\lfo, [\out, ~lfoBus.index]);
+
+
+// Synth array for voice allocation
+~synths = Array.fill(nbVoices, {
+    Synth(\rgbSynth, [\out, ~bus, \lfoBus, ~lfoBus.index], target: ~synthGroup, addAction: \addToTail)
+});
+
+
+// Filter envelope
+~filterEnv = Synth(\filterEnv, [\out, ~filterEnvBus.index]);
+
+
+// Array to keep in memory active synths (i.e. active notes)
+~activeNotes = Array.fill(nbVoices, { nil });
+
+
+// Function to modify a parameter for all synths
+~setSynthsParam = { |param, value|
+    ~synths.do { |synth|
+        synth.set(param, value);
+    };
+};
+
+
+~filter = Synth(\lpf, [
+	\in, ~bus,
+	\out, ~fxBus,
+	\lfoBus, ~lfoBus.index,
+	\envBus, ~filterEnvBus.index
+], target: ~filterGroup, addAction: \addToTail);
+
+
+~vst = Synth(\juceVST, [\in, ~fxBus, \out, 0], addAction: \addToTail);
+
+
+~ctl = VSTPluginController(~vst);
+
+// Open the JUCE plugin as a VST3
+~ctl.open(vst3Path, info: true, verbose: true, editor: true);
+//~ctl.editor;
+
+
+"Voice allocation arrays loaded".postln
+)
+
+
+//~setSynthsParam.(\lfoDepth, 0.05);
+
+//~filter.set(\cutoff, 10000, \resonance, 0, \lfoDepth, 2, \envDepth, 0);
+
+//~filterEnv.set(\attack, 0, \decay, 0, \sustain, 0);

+ 0 - 44
SC/3_effects_synthdefs.scd

@@ -1,44 +0,0 @@
-(
-// Simple reverb effect
-SynthDef(\reverb, { |in=0, out=0, mix=0.3, room=0.5, damp=0.5|
-    var sig, wet;
-    sig = In.ar(in, 2);
-    wet = FreeVerb.ar(sig, mix, room, damp);
-    Out.ar(out, wet);
-}).add;
-
-// Delay effect with feedback
-SynthDef(\delay, { |in=0, out=0, delaytime=0.5, feedback=0.5, mix=0.5|
-    var sig, wet, delayed;
-    sig = In.ar(in, 2);
-    delayed = CombL.ar(sig, 2.0, delaytime, feedback * 3);
-    wet = (sig * (1 - mix)) + (delayed * mix);
-    Out.ar(out, wet);
-}).add;
-
-// Low-pass filter effect
-SynthDef(\lpf, { |in=0, out=0, cutoff=1000, res=0.5|
-    var sig;
-    sig = In.ar(in, 2);
-    sig = RLPF.ar(sig, cutoff, res);
-    Out.ar(out, sig);
-}).add;
-
-// High-pass filter effect
-SynthDef(\hpf, { |in=0, out=0, cutoff=1000, res=0.5|
-    var sig;
-    sig = In.ar(in, 2);
-    sig = RHPF.ar(sig, cutoff, res);
-    Out.ar(out, sig);
-}).add;
-
-// Distortion effect
-SynthDef(\distortion, { |in=0, out=0, amount=0.5, mix=0.5|
-    var sig, dist;
-    sig = In.ar(in, 2);
-    dist = (sig * amount).tanh;
-    Out.ar(out, (sig * (1 - mix)) + (dist * mix));
-}).add;
-
-"Effects SynthDefs loaded".postln;
-)

+ 0 - 38
SC/4_modulation_synthdefs.scd

@@ -1,38 +0,0 @@
-(
-// Low Frequency Oscillator for parameter modulation
-SynthDef(\lfo, { |out=0, freq=1, min=0, max=1, waveform=0|
-    var lfo;
-
-    // Select waveform based on parameter
-    lfo = Select.kr(waveform, [
-        SinOsc.kr(freq),        // Sine wave (waveform=0)
-        LFTri.kr(freq),         // Triangle wave (waveform=1)
-        LFSaw.kr(freq),         // Sawtooth wave (waveform=2)
-        LFPulse.kr(freq, 0, 0.5) // Square wave (waveform=3)
-    ]);
-
-    // Scale to range
-    lfo = lfo.range(min, max);
-
-    // Output to control bus
-    Out.kr(out, lfo);
-}).add;
-
-// ADSR envelope generator
-SynthDef(\envelope, { |out=0, gate=1, attack=0.01, decay=0.3, sustain=0.5, release=1|
-    var env = EnvGen.kr(
-        Env.adsr(attack, decay, sustain, release),
-        gate,
-        doneAction: 2
-    );
-    Out.kr(out, env);
-}).add;
-
-// Random value generator with controllable rate
-SynthDef(\randomGen, { |out=0, freq=1, min=0, max=1|
-    var rand = LFNoise2.kr(freq).range(min, max);
-    Out.kr(out, rand);
-}).add;
-
-"Modulation SynthDefs loaded".postln;
-)

+ 302 - 0
SC/4_osc_communication.scd

@@ -0,0 +1,302 @@
+// Module 5: OSC Communication Setup - MODIFIED FOR IDRAW OSC
+// Save as "5_osc_communication.scd"
+
+(
+// Clear any existing OSC definitions
+OSCdef.freeAll;
+
+// Variables to track current pen type and color
+~currentPenType = "\pen";
+~currentColor = (r: 0.0, g: 0.0, b: 1.0); // Default blue
+~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0, a: 1); //Default pad values
+
+
+// Define OSC responder for iDraw touch data
+~changeEffectParams = {
+    var x = ~currentPadValues.x;
+    var y = ~currentPadValues.y;
+    var pressure = ~currentPadValues.pressure;
+	var a = ~currentPadValues.a;
+
+    // Log the received data
+    //["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;
+
+    // Handle touch based on current pen type
+    switch(~currentPenType,
+        // Pen - Controls amplitude envelope
+		"/pen", {
+            var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
+
+			~setSynthsParam.(\ampAttack, ampAttack);
+			~setSynthsParam.(\ampRelease, ampRelease);
+
+            //["Amplitude envelope:", ampAttack, ampRelease].postln;
+        },
+
+        // Monoline - Controls filter envelope
+		"/monoline", {
+            var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var filterDecay = x.linexp(-0.5, 0.5, 0.001, 10);
+			var envDepth = a.linlin(0, 1, 50, 0.001);
+
+			~filterEnv.set(\attack, filterAttack);
+			~filterEnv.set(\decay, filterDecay);
+			~filter.set(\envDepth, envDepth);
+
+
+            //["Filter envelope:", filterAttack, filterDecay, envDepth].postln;
+        },
+
+        // Marker - Controls pitch envelope
+		"/marker", {
+            var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var pitchDecay = x.linexp(-0.5, 0.5, 0.001, 10);
+			var pitchRatio = a.linexp(0, 1, 10, 1);
+
+			~setSynthsParam.(\pitchAttack, pitchAttack);
+			~setSynthsParam.(\pitchDecay, pitchDecay);
+			~setSynthsParam.(\pitchRatio, pitchRatio);
+
+            //["Pitch envelope:", pitchAttack, pitchDecay, pitchRatio].postln;
+        },
+
+        // Pencil - Effect preset 1
+		"/pencil", {
+            // Apply Preset 1 effects
+            ~filter.set(
+                \cutoff, x.linexp(-0.5, 0.5, 100, 18000),
+                \resonance, y.linlin(-0.5, 0.5, 0, 1),
+				\lfoDepth, pressure.linlin(1, 8, 0, 4)
+            );
+
+            ~lfo.set(
+                \freq, x.linlin(-0.5, 0.5, 0, 15),
+				\waveform, 2
+            );
+
+			~ctl.set(9, y.linlin(-0.5, 0.5, 0, 1));
+
+            //["Pencil preset:", "Cutoff", x.linexp(-0.5, 0.5, 20, 18000), "LFO", x.linlin(-0.5, 0.5, 0, 15)].postln;
+        },
+
+        // Crayon - Effect preset 2
+		"/crayon", {
+            // Apply Preset 2 effects
+            ~lfo.set(
+                \freq, x.linlin(-0.5, 0.5, 15, 1),
+				\waveform, 3
+            );
+
+            ~filter.set(
+                \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
+                \resonance, pressure.linlin(1, 5, 0, 1),
+				\lfoDepth, x.linlin(-0.5, 0.5, 0, 3)
+            );
+
+
+			~ctl.set(10, y.linlin(-0.5, 0.5, 0, 1)); // Reverb dry/wet
+
+			~ctl.set(8, x.linlin(-0.5, 0.5, 0.001, 1.0)); // Delay amount
+
+
+            //["Crayon preset:", "LFO", x.linlin(-0.5, 0.5, 15, 1), "Filter", y.linexp(-0.5, 0.5, 20, 18000)].postln;
+        },
+
+        // Fountain pen - Effect preset 3 (placeholder)
+		"/fountainPen", {
+            // Apply Preset 3 effects
+			~lfo.set(
+                \freq, x.linlin(-0.5, 0.5, 1, 15),
+				\waveform, 0
+            );
+
+			~filter.set(
+				\lfoDepth, 0
+            );
+
+			~setSynthsParam.(\lfoDepth, pressure.linlin(1, 5, 0, 0.5));
+
+			//["fountainPen preset:", "LFO Depth", pressure.linlin(1, 5, 0, 0.5), "LFO Freq", x.linlin(-0.5, 0.5, 1, 15)].postln;
+
+        },
+
+        // Water color - Effect preset 4 (placeholder)
+		"/waterColor", {
+            // Apply Preset 4 effects (TBD in documentation)
+            ["Water color preset (TBD)"].postln;
+        }
+    );
+};
+
+
+// ----- OSC Pad Vaues -----
+// OSC responder for x coordinate
+OSCdef(\xOSC, { |msg, time, addr, port|
+    var x = msg[1].asFloat;
+
+    // Update current pad value and change effects
+    ~currentPadValues.x = x;
+	~changeEffectParams.value;
+
+}, '/aspectX');
+
+// OSC responder for y coordinate
+OSCdef(\yOSC, { |msg, time, addr, port|
+    var y = msg[1].asFloat;
+
+    // Update current pad value and change effects
+    ~currentPadValues.y = y;
+	~changeEffectParams.value;
+
+}, '/aspectY');
+
+// OSC responder for pressure coordinate
+OSCdef(\pressureOSC, { |msg, time, addr, port|
+    var pressure = msg[1].asFloat;
+
+    // Update current pad value and change effects
+    ~currentPadValues.pressure = pressure;
+	~changeEffectParams.value;
+
+}, '/pressure');
+
+
+
+
+// ----- OSC Pen Types -----
+// OSC responder for pen
+OSCdef(\penOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/pen');
+
+// OSC responder for monoline
+OSCdef(\monolineOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/monoline');
+
+// OSC responder for marker
+OSCdef(\markerOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/marker');
+
+// OSC responder for pencil
+OSCdef(\pencilOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		~initializePreset1.value;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/pencil');
+
+// OSC responder for crayon
+OSCdef(\crayonOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		~initializePreset2.value;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/crayon');
+
+// OSC responder for fountainPen
+OSCdef(\fountainPenOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		~initializePreset3.value;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/fountainPen');
+
+// OSC responder for waterColor
+OSCdef(\waterColorOSC, { |msg, time, addr, port|
+    var penType = msg[1].asFloat;
+
+	if (penType == 1.0) {
+		~currentPenType = msg[0].asString;
+		~initializePreset4.value;
+		["Current pen type:", ~currentPenType].postln;
+	}
+
+}, '/waterColor');
+
+
+
+
+// ----- OSC Drawing Width -----
+OSCdef(\opacityOSC, { |msg, time, addr, port|
+    var a = msg[1].asFloat;
+	~currentPadValues.a = a;
+
+}, '/a');
+
+
+// ----- OSC RGB Colors -----
+// OSC responder for red changes
+OSCdef(\redOSC, { |msg, time, addr, port|
+    var component = msg[1].asFloat;
+
+    // Update current color
+    ~currentColor.r = component;
+	~setSynthsParam.(\redAmt, component);
+
+    //["Color changed:", ~currentColor].postln;
+}, '/r');
+
+// OSC responder for green changes
+OSCdef(\greenOSC, { |msg, time, addr, port|
+    var component = msg[1].asFloat;
+
+    // Update current color
+    ~currentColor.g = component;
+	~setSynthsParam.(\greenAmt, component);
+
+    //["Color changed:", ~currentColor].postln;
+}, '/g');
+
+// OSC responder for blue changes
+OSCdef(\blueOSC, { |msg, time, addr, port|
+    var component = msg[1].asFloat;
+
+    // Update current color
+    ~currentColor.b = component;
+	~setSynthsParam.(\blueAmt, component);
+
+    //["Color changed:", ~currentColor].postln;
+}, '/b');
+
+
+
+
+
+// Start the OSC server on port 57120 (default SuperCollider port)
+thisProcess.openUDPPort(57120);
+"OSC server ready on port 57120".postln;
+"Ready to receive data from iDraw OSC app".postln;
+)

+ 0 - 22
SC/4b_lfo_effects.scd

@@ -1,22 +0,0 @@
-(
-// LFO SynthDef with multiple waveform options
-SynthDef(\lfoEffect, { |out=0, freq=1, min=0, max=1, waveform=0, target=0|
-    var lfo;
-
-    // Select waveform based on parameter
-    lfo = Select.kr(waveform, [
-        SinOsc.kr(freq),        // Sine wave (waveform=0)
-        LFTri.kr(freq),         // Triangle wave (waveform=1)
-        LFSaw.kr(freq, 0, -1),  // Decreasing sawtooth (waveform=2)
-        LFPulse.kr(freq, 0, 0.5) // Square wave (waveform=3)
-    ]);
-
-    // Scale to range
-    lfo = lfo.range(min, max);
-
-    // Output to control bus
-    Out.kr(out, lfo);
-}).add;
-
-"Enhanced LFO effects loaded".postln;
-)

+ 59 - 0
SC/5_midi_controller.scd

@@ -0,0 +1,59 @@
+// MIDI note handling
+(
+var midiIn, synths, activeNotes;
+
+// Connect to MIDI
+MIDIClient.init;
+MIDIIn.connectAll;
+
+
+// Note On: add num to activeNotes and set synth gate to 1
+MIDIdef.noteOn(\noteOn, { |vel, num, chan, src|
+    var freq = num.midicps;
+	var index;
+
+	//postln("Note On: " + num + " Velocity: " + vel);
+
+    if (vel > 0) {
+
+		// Find first available (nil) slot
+		index = ~activeNotes.detectIndex({ |s| s.isNil });
+        if (index.notNil) {
+			~synths[index].set(\gate, 1);
+			~synths[index].set(\freq, freq);
+			~synths[index].set(\amp, vel/127);
+            ~activeNotes[index] = num; // Map note to synth index
+			~filterEnv.set(\gate, 1);  // Triggers the filter envelope
+        } {
+            "No available synth slots!".postln;
+        }
+
+    } { // Treat as noteOff if it is a noteOn with velocity 0
+		index = ~activeNotes.detectIndex({ |s| (s == num) });
+		if (index.notNil) {
+			~activeNotes[index] = nil;
+			~synths[index].set(\gate, 0);
+			~filterEnv.set(\gate, 0); // Releases the filter envelope
+		}
+	}
+});
+
+// Note Off: set synth gate to 0 and remove num from activeNotes
+MIDIdef.noteOff(\noteOff, { |vel, num, chan, src|
+	var index;
+
+	//postln("Note Off: " + num + " Velocity: " + vel);
+
+	index = ~activeNotes.detectIndex({ |s| (s == num) });
+	if (index.notNil) {
+		~activeNotes[index] = nil;
+		~synths[index].set(\gate, 0);
+		~filterEnv.set(\gate, 0); // Releases the filter envelope
+	}
+});
+
+
+// Run these functions directly
+"MIDI functions loaded.".postln;
+)
+

+ 0 - 183
SC/5_osc_communication.scd

@@ -1,183 +0,0 @@
-// Module 5: OSC Communication Setup - MODIFIED FOR IDRAW OSC
-// Save as "5_osc_communication.scd"
-
-(
-// Clear any existing OSC definitions
-OSCdef.freeAll;
-
-// Variables to track current pen type and color
-~currentPenType = \pen;
-~currentColor = (r: 0, g: 0, b: 1); // Default blue
-
-// Define OSC responder for iDraw touch data
-OSCdef(\touchOSC, { |msg, time, addr, port|
-    var x = msg[1].asFloat;
-    var y = msg[2].asFloat;
-    var pressure = msg[3].asFloat;
-
-    // Log the received data
-    ["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;
-
-    // Handle touch based on current pen type
-    switch(~currentPenType,
-        // Pen - Controls amplitude envelope
-        \pen, {
-            var attack = x.linlin(-0.5, 0.5, 0, 5);
-            var release = y.linlin(-0.5, 0.5, 0, 10);
-            var freq = x.linexp(-0.5, 0.5, 100, 2000);
-
-            // Generate sound with RGB-controlled waveform mix
-            var synth = Synth(\rgbSynth, [
-                \out, ~sourceBus ? 0,
-                \freq, freq,
-                \amp, pressure.linlin(1, 8, 0.1, 0.8),
-                \attack, attack,
-                \release, release,
-                \redAmt, ~currentColor.r,
-                \greenAmt, ~currentColor.g,
-                \blueAmt, ~currentColor.b
-            ]);
-
-            ["Amplitude envelope:", attack, release].postln;
-        },
-
-        // Monoline - Controls filter envelope
-        \monoline, {
-            var attack = x.linlin(-0.5, 0.5, 0, 5);
-            var release = y.linlin(-0.5, 0.5, 0, 10);
-            var freq = x.linexp(-0.5, 0.5, 100, 2000);
-
-            // Generate sound with filter envelope
-            var synth = Synth(\rgbFilterSynth, [
-                \out, ~sourceBus ? 0,
-                \freq, freq,
-                \amp, pressure.linlin(1, 8, 0.1, 0.8),
-                \attack, attack,
-                \release, release,
-                \filterAttack, attack,
-                \filterRelease, release,
-                \redAmt, ~currentColor.r,
-                \greenAmt, ~currentColor.g,
-                \blueAmt, ~currentColor.b
-            ]);
-
-            ["Filter envelope:", attack, release].postln;
-        },
-
-        // Marker - Controls pitch envelope
-        \marker, {
-            var attack = x.linlin(-0.5, 0.5, 0, 5);
-            var release = y.linlin(-0.5, 0.5, 0, 10);
-            var freq = x.linexp(-0.5, 0.5, 100, 2000);
-
-            // Generate sound with pitch envelope
-            var synth = Synth(\rgbPitchSynth, [
-                \out, ~sourceBus ? 0,
-                \freq, freq,
-                \amp, pressure.linlin(1, 8, 0.1, 0.8),
-                \attack, attack,
-                \release, release,
-                \pitchAttack, attack,
-                \pitchRelease, release,
-                \redAmt, ~currentColor.r,
-                \greenAmt, ~currentColor.g,
-                \blueAmt, ~currentColor.b
-            ]);
-
-            ["Pitch envelope:", attack, release].postln;
-        },
-
-        // Pencil - Effect preset 1
-        \pencil, {
-            // Apply Preset 1 effects
-            ~filterSynth.set(
-                \cutoff, x.linexp(-0.5, 0.5, 20, 18000),
-                \res, y.linlin(-0.5, 0.5, 0, 1)
-            );
-
-            ~lfoSynth.set(
-                \freq, x.linlin(-0.5, 0.5, 0, 15),
-                \intensity, pressure.linlin(1, 8, 0, 1)
-            );
-
-            ~reverbSynth.set(
-                \roomsize, y.linlin(-0.5, 0.5, 0.1, 0.9)
-            );
-
-            ["Pencil preset:", "Cutoff", x.linexp(-0.5, 0.5, 20, 18000), "LFO", x.linlin(-0.5, 0.5, 0, 15)].postln;
-        },
-
-        // Crayon - Effect preset 2
-        \crayon, {
-            // Apply Preset 2 effects
-            ~lfoSynth.set(
-                \freq, x.linlin(-0.5, 0.5, 15, 1),
-                \intensity, x.linlin(-0.5, 0.5, 0, 1)
-            );
-
-            ~delaySynth.set(
-                \delaytime, x.linlin(-0.5, 0.5, 0.01, 1.0)
-            );
-
-            ~filterSynth.set(
-                \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
-                \res, pressure.linlin(1, 5, 0, 1)
-            );
-
-            ~reverbSynth.set(
-                \mix, y.linlin(-0.5, 0.5, 0, 1)
-            );
-
-            ["Crayon preset:", "LFO", x.linlin(-0.5, 0.5, 15, 1), "Filter", y.linexp(-0.5, 0.5, 20, 18000)].postln;
-        },
-
-        // Fountain pen - Effect preset 3 (placeholder)
-        \fountainPen, {
-            // Apply Preset 3 effects (TBD in documentation)
-            ["Fountain pen preset (TBD)"].postln;
-        },
-
-        // Water color - Effect preset 4 (placeholder)
-        \waterColor, {
-            // Apply Preset 4 effects (TBD in documentation)
-            ["Water color preset (TBD)"].postln;
-        }
-    );
-}, '/touch');
-
-// OSC responder for pen type selection
-OSCdef(\penTypeOSC, { |msg, time, addr, port|
-    var penType = msg[1].asSymbol;
-
-    // Update current pen type
-    ~currentPenType = penType;
-
-    ["Pen type changed:", penType].postln;
-
-    // Initialize relevant effects based on pen type
-    switch(penType,
-        \pencil, { ~initializePreset1.value; },
-        \crayon, { ~initializePreset2.value; },
-        \fountainPen, { ~initializePreset3.value; },
-        \waterColor, { ~initializePreset4.value; }
-    );
-}, '/pen');
-
-// OSC responder for color changes
-OSCdef(\colorOSC, { |msg, time, addr, port|
-    var r = msg[1].asFloat;
-    var g = msg[2].asFloat;
-    var b = msg[3].asFloat;
-
-    // Update current color
-    ~currentColor = (r: r, g: g, b: b);
-
-    ["Color changed:", r, g, b].postln;
-}, '/color');
-
-// Start the OSC server on port 57120 (default SuperCollider port)
-thisProcess.openUDPPort(57120);
-"OSC server ready on port 57120".postln;
-"Registered OSC commands: /touch, /pen, /color".postln;
-"Ready to receive data from iDraw OSC app".postln;
-)

+ 0 - 163
SC/6_test_functions.scd

@@ -1,163 +0,0 @@
-(
-// Function to start effects chain
-~startEffectsChain = {
-    // Create audio buses for effects chain
-    ~sourceBus = Bus.audio(s, 2);
-    ~filterBus = Bus.audio(s, 2);
-    ~delayBus = Bus.audio(s, 2);
-    ~reverbBus = Bus.audio(s, 2);
-
-    // Create control buses for modulation
-    ~lfoControlBus = Bus.control(s, 1);
-
-    // Create effects synths in chain
-    ~lfoSynth = Synth(\lfoEffect, [
-        \out, ~lfoControlBus,
-        \freq, 1,
-        \min, 100,
-        \max, 5000,
-        \waveform, 0,
-        \target, 0
-    ]);
-
-    ~filterSynth = Synth(\lpf, [
-        \in, ~sourceBus,
-        \out, ~delayBus,
-        \cutoff, 1000,
-        \res, 0.5
-    ]);
-
-    ~delaySynth = Synth(\delay, [
-        \in, ~delayBus,
-        \out, ~reverbBus,
-        \delaytime, 0.4,
-        \feedback, 0.3,
-        \mix, 0.3
-    ], ~filterSynth, \addAfter);
-
-    ~reverbSynth = Synth(\reverb, [
-        \in, ~reverbBus,
-        \out, 0,
-        \mix, 0.2,
-        \room, 0.5,
-        \damp, 0.5
-    ], ~delaySynth, \addAfter);
-
-    // Create a mapping for the LFO to control the filter
-    s.sync;
-    ~lfoControlBus.asMap.postln;
-    ~filterSynth.map(\cutoff, ~lfoControlBus);
-
-    // Store the effects chain nodes in an array for easy access
-    ~effectsChain = [~lfoSynth, ~filterSynth, ~delaySynth, ~reverbSynth];
-
-    "Effects chain started with LFO mapping".postln;
-};
-// Function to stop effects chain
-~stopEffectsChain = {
-    if(~effectsChain.notNil, {
-        ~effectsChain.do(_.free);
-        ~effectsChain = nil;
-    });
-
-    if(~sourceBus.notNil, { ~sourceBus.free; ~sourceBus = nil; });
-    if(~reverbBus.notNil, { ~reverbBus.free; ~reverbBus = nil; });
-    if(~delayBus.notNil, { ~delayBus.free; ~delayBus = nil; });
-
-    "Effects chain stopped".postln;
-};
-
-// Function to reset the entire system
-~resetSystem = {
-    ~stopEffectsChain.value;
-    OSCdef.freeAll;
-
-    // Reload OSC definitions
-    thisProcess.interpreter.executeFile("5_osc_communication.scd");
-
-    "System reset complete".postln;
-	~touchSynths = ();  // Clear any active touch synths
-
-};
-
-// Test function for parameter changes
-~testParameters = {
-    // Start effects chain if not already running
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    // Test different oscillator types with varying parameters
-    [
-        [\sineTone, 440, 0.3, -0.5, 0.05, 0.5],
-        [\squareTone, 330, 0.2, 0, 0.01, 0.8],
-        [\sawTone, 220, 0.15, 0.5, 0.1, 1.2],
-        [\triTone, 550, 0.25, -0.2, 0.02, 0.7],
-        [\fmTone, 660, 0.2, 0.3, 0.05, 1.0]
-    ].do { |params, i|
-        var synthType, freq, amp, pan, attack, release;
-        #synthType, freq, amp, pan, attack, release = params;
-
-        // Create the synth with the specified parameters
-        Synth(synthType, [
-            \out, ~sourceBus,
-            \freq, freq,
-            \amp, amp,
-            \pan, pan,
-            \attack, attack,
-            \release, release
-        ]);
-
-        // Change effect parameters for demonstration
-        ~filterSynth.set(\cutoff, 500 + (i * 1000));
-        ~delaySynth.set(\mix, 0.2 + (i * 0.1));
-        ~reverbSynth.set(\room, 0.3 + (i * 0.1));
-
-        // Log the current sound
-        ["Testing synth:", synthType, freq, amp].postln;
-
-        // Wait between notes
-        0.8.wait;
-    };
-
-    // Clean up
-    "Parameter test complete".postln;
-};
-
-// Function to simulate Arduino touch input
-~simulateTouch = { |numTouches=10, duration=5|
-    var endTime = SystemClock.seconds + duration;
-
-    "Starting touch simulation for % seconds".format(duration).postln;
-
-    // Start the effects chain
-    ~startEffectsChain.value;
-
-    // Generate random touches until the duration expires
-    while { SystemClock.seconds < endTime } {
-        var x = 1.0.rand;
-        var y = 1.0.rand;
-        var pressure = 0.3 + 0.7.rand;
-        var color = 5.rand;  // 0-4 for different synth types
-
-        // Send the simulated touch data through our OSC handler
-        OSCdef(\touchOSC).value(['/touch', x, y, pressure, color], nil, nil, nil);
-
-        // Random wait time between touches
-        (0.1 + 0.3.rand).wait;
-    };
-
-    "Touch simulation complete".postln;
-};
-
-// Run parameter test in a Routine
-~runParameterTest = {
-    Routine(~testParameters).play;
-};
-
-// Run touch simulation in a Routine
-~runTouchSimulation = { |duration=5|
-    Routine({ ~simulateTouch.value(10, duration) }).play;
-};
-
-"Test functions loaded".postln;
-)
-

+ 0 - 47
SC/6b_effect_presets.scd

@@ -1,47 +0,0 @@
-(
-// Initialize Effect Preset 1 (Pencil)
-~initializePreset1 = {
-    // Make sure effects chain exists
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    // Set LFO to specific settings for Preset 1
-    ~lfoSynth.set(
-        \waveform, 2,  // Decreasing sawtooth
-        \target, 0     // Target filter cutoff
-    );
-
-    "Initialized Preset 1 (Pencil) - LFO + Filter + Reverb".postln;
-};
-
-// Initialize Effect Preset 2 (Crayon)
-~initializePreset2 = {
-    // Make sure effects chain exists
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    // Set LFO to specific settings for Preset 2
-    ~lfoSynth.set(
-        \waveform, 3,  // Square wave
-        \target, 0     // Target filter cutoff
-    );
-
-    "Initialized Preset 2 (Crayon) - LFO + Filter + Reverb + Delay".postln;
-};
-
-// Initialize Effect Preset 3 (Fountain Pen)
-~initializePreset3 = {
-    // Make sure effects chain exists
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    "Initialized Preset 3 (Fountain Pen) - TBD".postln;
-};
-
-// Initialize Effect Preset 4 (Water Color)
-~initializePreset4 = {
-    // Make sure effects chain exists
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    "Initialized Preset 4 (Water Color) - TBD".postln;
-};
-
-"Effect preset initializers loaded".postln;
-)

+ 0 - 110
SC/7_idraw_connection.scd

@@ -1,110 +0,0 @@
-(
-// Function to test iDraw OSC connection
-~testiDrawConnection = {
-    var interfaces, ip;
-
-    // Log local IP and port information
-    "SuperCollider OSC server info for iDraw OSC connection:".postln;
-    "Hostname: %".format(Platform.myHostName).postln;
-    "Local IP addresses:".postln;
-
-    try {
-        interfaces = "ifconfig".unixCmdGetStdOutLines;
-        interfaces.do { |line|
-            if(line.containsi("inet ") && line.containsStringAt(0, "inet").not, {
-                line = line.replace("\t", "").replace(" ", "");
-                ip = line.findRegexp("inet([0-9.]+)")[1][1];
-                "  %".format(ip).postln;
-            });
-        };
-    } { |err|
-        "Could not detect network interfaces: %".format(err).postln;
-    };
-
-    // Alternate way to find IP addresses that might work better on some systems
-    "Alternative method to find IP addresses:".postln;
-    try {
-        thisProcess.platform.getNetworkNameList.do { |netname|
-            var addr = netname.findRegexp("\\d+\\.\\d+\\.\\d+\\.\\d+");
-            if(addr.size > 0, {
-                "  %".format(addr[0][1]).postln;
-            });
-        };
-    } { |err|
-        "Could not use network name list method: %".format(err).postln;
-    };
-
-    "OSC Port: 57120".postln;
-    "".postln;
-    "To connect from iDraw OSC:".postln;
-    "1. Ensure iPad/iPhone is on the same WiFi network".postln;
-    "2. Open iDraw OSC app".postln;
-    "3. Set the host/IP to one of the above addresses".postln;
-    "4. Set the port to 57120".postln;
-    "5. Ensure iDraw OSC is sending messages with these addresses:".postln;
-    "   - /touch (x, y, pressure)".postln;
-    "   - /pen (pen type)".postln;
-    "   - /color (r, g, b)".postln;
-};
-
-// Function to simulate iDraw OSC messages for testing
-~simulateiDrawTouch = { |duration=10|
-    var endTime, penTypes, penType, r, g, b;
-
-    endTime = SystemClock.seconds + duration;
-    "Simulating iDraw OSC touch events for % seconds".format(duration).postln;
-
-    // Start the effects chain if needed
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    // First set a pen type
-    penTypes = [\pen, \monoline, \marker, \pencil, \crayon, \fountainPen, \waterColor];
-    penType = penTypes.choose;
-
-    OSCdef(\penTypeOSC).value(['/pen', penType], nil, nil, nil);
-
-    // Set a random color
-    r = 1.0.rand;
-    g = 1.0.rand;
-    b = 1.0.rand;
-
-    OSCdef(\colorOSC).value(['/color', r, g, b], nil, nil, nil);
-
-    // Generate simulated touch events
-    fork {
-        while { SystemClock.seconds < endTime } {
-            var x = (-0.5 + 1.0.rand);
-            var y = (-0.5 + 1.0.rand);
-            var pressure = 1 + 7.rand;
-
-            // Send touch message
-            OSCdef(\touchOSC).value(['/touch', x, y, pressure], nil, nil, nil);
-
-            // Wait random time between touch events
-            rrand(0.1, 0.3).wait;
-
-            // Occasionally change pen type or color
-            if(0.1.coin, {
-                penType = penTypes.choose;
-                OSCdef(\penTypeOSC).value(['/pen', penType], nil, nil, nil);
-                "Changed to pen type: %".format(penType).postln;
-            });
-
-            if(0.1.coin, {
-                r = 1.0.rand;
-                g = 1.0.rand;
-                b = 1.0.rand;
-                OSCdef(\colorOSC).value(['/color', r, g, b], nil, nil, nil);
-                "Changed to color: % % %".format(r, g, b).postln;
-            });
-        };
-
-        "iDraw OSC simulation complete".postln;
-    };
-};
-
-// Run these functions directly
-"iDraw OSC connection test functions loaded.".postln;
-"To test connection info, run: ~testiDrawConnection.value".postln;
-"To simulate iDraw OSC events, run: ~simulateiDrawTouch.value(20)".postln;
-)

+ 0 - 82
SC/8_mobile_connection.scd

@@ -1,82 +0,0 @@
-(
-// Function to test mobile connection
-~testMobileConnection = {
-    // Log local IP and port information
-    "SuperCollider OSC server info:".postln;
-    "Hostname: %".format(Platform.myHostName).postln;
-    "Local IP addresses:".postln;
-
-    try {
-        var interfaces = "ifconfig".unixCmdGetStdOutLines;
-        interfaces.do { |line|
-            if(line.containsi("inet ") && line.containsStringAt(0, "inet").not, {
-                line = line.replace("\t", "").replace(" ", "");
-                var ip = line.findRegexp("inet([0-9.]+)")[1][1];
-                "  %".format(ip).postln;
-            });
-        };
-    } { |err|
-        "Could not detect network interfaces: %".format(err).postln;
-    };
-
-    "OSC Port: 57120".postln;
-    "".postln;
-    "To connect from a mobile device:".postln;
-    "1. Ensure mobile device is on the same WiFi network".postln;
-    "2. Use one of the IP addresses above in your mobile OSC app".postln;
-    "3. Set the port to 57120".postln;
-};
-
-// Function to simulate mobile touch for testing without a mobile device
-~simulateMobileTouch = { |duration=10|
-    var endTime = SystemClock.seconds + duration;
-    var touchId = 1000;
-
-    "Simulating mobile touch events for % seconds".format(duration).postln;
-
-    // Start the effects chain if needed
-    if(~effectsChain.isNil, { ~startEffectsChain.value; });
-
-    // Generate simulated touch events
-    fork {
-        while { SystemClock.seconds < endTime } {
-            var x = 1.0.rand;
-            var y = 1.0.rand;
-            var pressure = 0.3 + 0.7.rand;
-            var state = [\began, \moved, \ended].choose;
-
-            // Create realistic touch sequences
-            if(state == \began, {
-                touchId = touchId + 1;
-                OSCdef(\touchOSC).value(['/touch', touchId, x, y, \began, pressure], nil, nil, nil);
-
-                // Simulate some movement for this touch
-                fork {
-                    var moveCount = rrand(3, 8);
-                    moveCount.do {
-                        0.1.wait;
-                        // Slight movement from original position
-                        x = (x + 0.1.rand2).clip(0, 1);
-                        y = (y + 0.1.rand2).clip(0, 1);
-                        OSCdef(\touchOSC).value(['/touch', touchId, x, y, \moved, pressure], nil, nil, nil);
-                    };
-
-                    // End the touch
-                    0.2.wait;
-                    OSCdef(\touchOSC).value(['/touch', touchId, x, y, \ended, pressure], nil, nil, nil);
-                };
-            });
-
-            // Wait random time between new touch events
-            rrand(0.2, 1.0).wait;
-        };
-
-        "Mobile touch simulation complete".postln;
-    };
-};
-
-// Run these functions directly
-"Mobile connection test functions loaded.".postln;
-"To test connection info, run: ~testMobileConnection.value".postln;
-"To simulate mobile touch events, run: ~simulateMobileTouch.value(20)".postln;
-)

+ 0 - 14
SC/main.scd

@@ -1,14 +0,0 @@
-// Initialize the system
-(
-s.waitForBoot({
-    "Initializing Interactive Sound Canvas...".postln;
-
-    // Start effects chain
-    ~startEffectsChain.value;
-
-    // System is ready for input
-    "System ready! Touch data can now be received via OSC.".postln;
-    "To test the system, run: ~runParameterTest.value".postln;
-    "To simulate touch input, run: ~runTouchSimulation.value(10)".postln;
-});
-)