فهرست منبع

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

Thomas GUFFROY 10 ماه پیش
والد
کامیت
8f3c60e4d5
6فایلهای تغییر یافته به همراه281 افزوده شده و 149 حذف شده
  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)