Explorar el Código

SC modules modified to take into account MIDI from keyboard and OSC from app

Thomas GUFFROY hace 6 meses
padre
commit
8f3c60e4d5
Se han modificado 6 ficheros con 281 adiciones y 149 borrados
  1. 4 1
      SC/1_environment_setup.scd
  2. 17 55
      SC/2b_rgb_synthdefs.scd
  3. 202 89
      SC/5_osc_communication.scd
  4. 3 3
      SC/8_mobile_connection.scd
  5. 51 0
      SC/9_midi_controller.scd
  6. 4 1
      SC/main.scd

+ 4 - 1
SC/1_environment_setup.scd

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

+ 17 - 55
SC/2b_rgb_synthdefs.scd

@@ -1,65 +1,22 @@
 (
 // 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;
+SynthDef(\rgbSynth, { |out=0, freq=440, amp=0.5, ampAttack=0.01, ampRelease=1,
+	filterAttack=0, filterRelease=0, filterMin=200, filterMax=5000,
+	pitchAttack=0, pitchRelease=0, pitchRatio=2,
+	redAmt=0.5, greenAmt=0.5, blueAmt=0.5|
 
-    // 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;
+    var env, gate, filterEnv, pitchEnv, red, green, blue, sig;
 
-    // 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;
+	gate = \gate.kr(1);
 
     // Amplitude envelope
-    ampEnv = EnvGen.kr(Env.perc(attack, release), doneAction: 2);
+    env = EnvGen.kr(Env.adsr(ampAttack, 0, 1, ampRelease), gate, 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);
+    filterEnv = EnvGen.kr(Env.adsr(filterAttack, 0, 1, filterRelease), gate);
 
     // Pitch envelope
-    pitchEnv = EnvGen.kr(Env.perc(pitchAttack, pitchRelease));
+    pitchEnv = EnvGen.kr(Env.adsr(pitchAttack, 0, 1, pitchRelease), gate);
 
     // Calculate modulated frequency
     freq = freq * (1 + (pitchEnv * (pitchRatio - 1)));
@@ -72,10 +29,15 @@ SynthDef(\rgbPitchSynth, { |out=0, freq=440, amp=0.5, attack=0.01, release=1,
     // Mix the waveforms
     sig = (red + green + blue) / 3;
 
-    // Apply amplitude envelope and output
-    sig = sig * ampEnv * amp;
+    // Apply filter with envelope control
+    sig = RLPF.ar(sig, filterEnv.linexp(0, 1, filterMin, filterMax), 0.8);
+
+    // Apply envelope and output
+    sig = sig * env * amp;
     Out.ar(out, sig!2);
 }).add;
 
-"RGB-controlled synthesizers loaded".postln;
+
+
+"RGB-controlled synthesizer loaded".postln;
 )

+ 202 - 89
SC/5_osc_communication.scd

@@ -7,13 +7,32 @@ OSCdef.freeAll;
 
 // Variables to track current pen type and color
 ~currentPenType = \pen;
-~currentColor = (r: 0, g: 0, b: 1); // Default blue
+~currentColor = (r: 0.0, g: 0.0, b: 1.0); // Default blue
+~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0); //Default pad values
+
+~synthParams = (
+	out: 0,
+	freq: 440,
+	amp: 0.5,
+	ampAttack: 0.01,
+	ampRelease: 1,
+	filterAttack: 0,
+	filterRelease: 0,
+	filterMin: 200,
+	filterMax: 5000,
+	pitchAttack: 0,
+	pitchRelease: 0,
+	pitchRatio: 2,
+	redAmt: 0.5,
+	greenAmt: 0.5,
+	blueAmt: 0.5
+);
 
 // 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;
+~changeEffectParams = {
+    var x = ~currentPadValues.x;
+    var y = ~currentPadValues.y;
+    var pressure = ~currentPadValues.pressure;
 
     // Log the received data
     ["Touch data:", x, y, pressure, ~currentPenType, ~currentColor].postln;
@@ -21,74 +40,40 @@ OSCdef(\touchOSC, { |msg, time, addr, port|
     // 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;
+		"/pen", {
+            var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
+
+			~synthParams.ampAttack = ampAttack;
+			~synthParams.ampRelease = ampRelease;
+
+            ["Amplitude envelope:", ampAttack, ampRelease].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;
+		"/monoline", {
+            var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var filterRelease = x.linexp(-0.5, 0.5, 0.001, 10);
+
+			~synthParams.filterAttack = filterAttack;
+			~synthParams.filterRelease = filterRelease;
+
+            ["Filter envelope:", filterAttack, filterRelease].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;
+		"/marker", {
+            var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
+            var pitchRelease = x.linexp(-0.5, 0.5, 0.001, 10);
+
+			~synthParams.pitchAttack = pitchAttack;
+			~synthParams.pitchRelease = pitchRelease;
+
+            ["Pitch envelope:", pitchAttack, pitchRelease].postln;
         },
 
         // Pencil - Effect preset 1
-        \pencil, {
+		"/pencil", {
             // Apply Preset 1 effects
             ~filterSynth.set(
                 \cutoff, x.linexp(-0.5, 0.5, 20, 18000),
@@ -108,7 +93,7 @@ OSCdef(\touchOSC, { |msg, time, addr, port|
         },
 
         // Crayon - Effect preset 2
-        \crayon, {
+		"/crayon", {
             // Apply Preset 2 effects
             ~lfoSynth.set(
                 \freq, x.linlin(-0.5, 0.5, 15, 1),
@@ -132,48 +117,176 @@ OSCdef(\touchOSC, { |msg, time, addr, port|
         },
 
         // Fountain pen - Effect preset 3 (placeholder)
-        \fountainPen, {
+		"/fountainPen", {
             // Apply Preset 3 effects (TBD in documentation)
             ["Fountain pen preset (TBD)"].postln;
         },
 
         // Water color - Effect preset 4 (placeholder)
-        \waterColor, {
+		"/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;
+// ----- OSC Pad Vaues -----
+// OSC responder for x coordinate
+OSCdef(\xOSC, { |msg, time, addr, port|
+    var x = msg[1].asFloat;
 
-    ["Pen type changed:", penType].postln;
+    // 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;
+	}
 
-    // 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;
+// 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 RGB Colors -----
+// OSC responder for red changes
+OSCdef(\redOSC, { |msg, time, addr, port|
+    var component = msg[1].asFloat;
 
     // Update current color
-    ~currentColor = (r: r, g: g, b: b);
+    ~currentColor.r = component;
+	~synthParams.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;
+	~synthParams.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;
+	~synthParams.blueAmt = component;
+
+    ["Color changed:", ~currentColor].postln;
+}, '/b');
+
+
+
 
-    ["Color changed:", r, g, b].postln;
-}, '/color');
 
 // Start the OSC server on port 57120 (default SuperCollider port)
 thisProcess.openUDPPort(57120);

+ 3 - 3
SC/8_mobile_connection.scd

@@ -1,17 +1,17 @@
 (
 // Function to test mobile connection
 ~testMobileConnection = {
-    // Log local IP and port information
+    var interfaces, ip; // Declare variables here
     "SuperCollider OSC server info:".postln;
     "Hostname: %".format(Platform.myHostName).postln;
     "Local IP addresses:".postln;
 
     try {
-        var interfaces = "ifconfig".unixCmdGetStdOutLines;
+        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];
+                ip = line.findRegexp("inet([0-9.]+)")[1][1];
                 "  %".format(ip).postln;
             });
         };

+ 51 - 0
SC/9_midi_controller.scd

@@ -0,0 +1,51 @@
+// MIDI note handling
+(
+var midiIn, synths;
+
+~synths = IdentityDictionary.new;  // Store active synths keyed by note number
+
+// Connect to MIDI
+MIDIClient.init;
+MIDIIn.connectAll;
+
+// Note On: create synth
+MIDIdef.noteOn(\noteOn, { |vel, num, chan, src|
+    var freq = num.midicps;
+
+	//postln("Note On: " + num + " Velocity: " + vel);
+
+    if (vel > 0) {
+        var synth = Synth(\rgbSynth, [
+			\freq, freq,
+			\amp, vel/127,
+			\ampAttack, ~synthParams.ampAttack,
+			\ampRelease, ~synthParams.ampRelease,
+			\filterAttack, ~synthParams.filterAttack,
+			\filterRelease, ~synthParams.filterRelease,
+			\pitchAttack, ~synthParams.pitchAttack,
+			\pitchRelease, ~synthParams.pitchRelease,
+			\redAmt, ~synthParams.redAmt,
+			\greenAmt, ~synthParams.greenAmt,
+			\blueAmt, ~synthParams.blueAmt
+		]);
+        ~synths[num] = synth;
+
+    } { // Treat as noteOff if it is a noteOn with velocity 0
+		//postln("Note On: " + num + " Velocity: " + vel);
+	    ~synths[num].set(\gate, 0);
+		~synths.removeAt(num);
+	}
+});
+
+// Note Off: release synth
+MIDIdef.noteOff(\noteOff, { |vel, num, chan, src|
+	//postln("Note Off: " + num + " Velocity: " + vel);
+    ~synths[num].set(\gate, 0);
+    ~synths.removeAt(num);
+});
+
+
+
+// Run these functions directly
+"MIDI functions loaded.".postln;
+)

+ 4 - 1
SC/main.scd

@@ -11,4 +11,7 @@ s.waitForBoot({
     "To test the system, run: ~runParameterTest.value".postln;
     "To simulate touch input, run: ~runTouchSimulation.value(10)".postln;
 });
-)
+)
+
+~runParameterTest.value
+~runTouchSimulation.value(10)