|
@@ -1,5 +1,5 @@
|
|
|
-// Module 5: OSC Communication Setup - FIXED FOR PROPER TOUCH MANAGEMENT
|
|
|
|
|
-// Save as "5_osc_communication.scd" (REPLACE THE PREVIOUS VERSION)
|
|
|
|
|
|
|
+// Module 5: OSC Communication Setup - MODIFIED FOR IDRAW OSC
|
|
|
|
|
+// Save as "5_osc_communication.scd"
|
|
|
|
|
|
|
|
(
|
|
(
|
|
|
// Clear any existing OSC definitions
|
|
// Clear any existing OSC definitions
|
|
@@ -10,278 +10,111 @@ OSCdef.freeAll;
|
|
|
~currentColor = (r: 0.0, g: 0.0, b: 1.0); // 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
|
|
~currentPadValues = (x: 0.0, y: 0.0, pressure: 1.0); //Default pad values
|
|
|
|
|
|
|
|
-// Touch state management
|
|
|
|
|
-~touchState = (
|
|
|
|
|
- isActive: false,
|
|
|
|
|
- currentSynth: nil,
|
|
|
|
|
- lastTriggerTime: 0,
|
|
|
|
|
- minTriggerInterval: 0.1 // Minimum time between new synths (100ms)
|
|
|
|
|
-);
|
|
|
|
|
-
|
|
|
|
|
-~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
|
|
|
|
|
-);
|
|
|
|
|
-
|
|
|
|
|
-// Track active synths to prevent memory leaks
|
|
|
|
|
-~activeSynths = IdentityDictionary.new;
|
|
|
|
|
-~synthCounter = 0;
|
|
|
|
|
-
|
|
|
|
|
-// Function to clean up old synths
|
|
|
|
|
-~cleanupSynths = {
|
|
|
|
|
- ~activeSynths.keysValuesDo({ |key, synth|
|
|
|
|
|
- if(synth.isPlaying.not, {
|
|
|
|
|
- ~activeSynths.removeAt(key);
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // If too many synths are active, force cleanup of oldest ones
|
|
|
|
|
- if(~activeSynths.size > 5, { // Reduced from 10 to 5
|
|
|
|
|
- var oldestKeys = ~activeSynths.keys.asArray.sort.copyRange(0, ~activeSynths.size - 3);
|
|
|
|
|
- oldestKeys.do({ |key|
|
|
|
|
|
- if(~activeSynths[key].notNil, {
|
|
|
|
|
- ~activeSynths[key].set(\gate, 0);
|
|
|
|
|
- ~activeSynths.removeAt(key);
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// Function to create a new synth safely (only when needed)
|
|
|
|
|
-~createSafeSynth = { |synthType = \rgbSynth, args|
|
|
|
|
|
- var synth, synthId;
|
|
|
|
|
-
|
|
|
|
|
- // Clean up old synths first
|
|
|
|
|
- ~cleanupSynths.value;
|
|
|
|
|
-
|
|
|
|
|
- // Create new synth
|
|
|
|
|
- synthId = ~synthCounter;
|
|
|
|
|
- ~synthCounter = ~synthCounter + 1;
|
|
|
|
|
-
|
|
|
|
|
- // Add default parameters if not provided
|
|
|
|
|
- args = args ++ [
|
|
|
|
|
- \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
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- synth = Synth(synthType, args);
|
|
|
|
|
- ~activeSynths[synthId] = synth;
|
|
|
|
|
-
|
|
|
|
|
- // Schedule automatic cleanup
|
|
|
|
|
- SystemClock.sched(~synthParams.ampAttack + ~synthParams.ampRelease + 1, {
|
|
|
|
|
- if(~activeSynths[synthId].notNil, {
|
|
|
|
|
- ~activeSynths[synthId].set(\gate, 0);
|
|
|
|
|
- ~activeSynths.removeAt(synthId);
|
|
|
|
|
- });
|
|
|
|
|
- nil; // Don't reschedule
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- synth;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// Function to handle touch begin (creates new synth)
|
|
|
|
|
-~handleTouchBegin = {
|
|
|
|
|
- var x = ~currentPadValues.x;
|
|
|
|
|
- var y = ~currentPadValues.y;
|
|
|
|
|
- var pressure = ~currentPadValues.pressure;
|
|
|
|
|
- var freq = x.linexp(-0.5, 0.5, 100, 2000);
|
|
|
|
|
- var amp = pressure.linlin(1, 8, 0.1, 0.5); // Reduced max amplitude
|
|
|
|
|
-
|
|
|
|
|
- // Only create sounds for envelope-controlling pen types
|
|
|
|
|
- if([\pen, \monoline, \marker].includes(~currentPenType.asSymbol), {
|
|
|
|
|
- // Release previous synth if it exists
|
|
|
|
|
- if(~touchState.currentSynth.notNil, {
|
|
|
|
|
- ~touchState.currentSynth.set(\gate, 0);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // Create new synth
|
|
|
|
|
- ~touchState.currentSynth = ~createSafeSynth.value(\rgbSynth, [
|
|
|
|
|
- \out, ~sourceBus ? 0,
|
|
|
|
|
- \freq, freq,
|
|
|
|
|
- \amp, amp
|
|
|
|
|
- ]);
|
|
|
|
|
-
|
|
|
|
|
- ~touchState.isActive = true;
|
|
|
|
|
- ~touchState.lastTriggerTime = SystemClock.seconds;
|
|
|
|
|
-
|
|
|
|
|
- ["Touch BEGIN - Sound triggered:", ~currentPenType, freq, amp].postln;
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// Function to handle touch movement (updates existing synth)
|
|
|
|
|
-~handleTouchMove = {
|
|
|
|
|
- var x = ~currentPadValues.x;
|
|
|
|
|
- var y = ~currentPadValues.y;
|
|
|
|
|
- var pressure = ~currentPadValues.pressure;
|
|
|
|
|
- var freq = x.linexp(-0.5, 0.5, 100, 2000);
|
|
|
|
|
- var amp = pressure.linlin(1, 8, 0.1, 0.5);
|
|
|
|
|
-
|
|
|
|
|
- // Only update if we have an active touch for envelope-controlling pens
|
|
|
|
|
- if(~touchState.isActive and: { ~touchState.currentSynth.notNil } and: {
|
|
|
|
|
- [\pen, \monoline, \marker].includes(~currentPenType.asSymbol)
|
|
|
|
|
- }, {
|
|
|
|
|
- // Update the existing synth parameters
|
|
|
|
|
- if(~touchState.currentSynth.isPlaying, {
|
|
|
|
|
- ~touchState.currentSynth.set(\freq, freq, \amp, amp);
|
|
|
|
|
- // Don't log every movement to avoid spam
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
|
|
|
|
|
-// Function to handle touch end (releases synth)
|
|
|
|
|
-~handleTouchEnd = {
|
|
|
|
|
- if(~touchState.currentSynth.notNil, {
|
|
|
|
|
- ~touchState.currentSynth.set(\gate, 0);
|
|
|
|
|
- ~touchState.currentSynth = nil;
|
|
|
|
|
- ~touchState.isActive = false;
|
|
|
|
|
-
|
|
|
|
|
- ["Touch END - Sound released"].postln;
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// Smart trigger function that decides what to do based on pressure changes
|
|
|
|
|
-~smartTriggerSound = {
|
|
|
|
|
- var currentTime = SystemClock.seconds;
|
|
|
|
|
- var pressure = ~currentPadValues.pressure;
|
|
|
|
|
-
|
|
|
|
|
- // Detect touch begin: pressure goes from low to high
|
|
|
|
|
- if(pressure > 2 and: { ~touchState.isActive.not }, {
|
|
|
|
|
- ~handleTouchBegin.value;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // Detect touch movement: pressure stays high and we have active touch
|
|
|
|
|
- if(pressure > 1 and: { ~touchState.isActive }, {
|
|
|
|
|
- ~handleTouchMove.value;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // Detect touch end: pressure goes to very low or zero
|
|
|
|
|
- if(pressure <= 1 and: { ~touchState.isActive }, {
|
|
|
|
|
- ~handleTouchEnd.value;
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// Function to update effect parameters safely
|
|
|
|
|
|
|
+// Define OSC responder for iDraw touch data
|
|
|
~changeEffectParams = {
|
|
~changeEffectParams = {
|
|
|
var x = ~currentPadValues.x;
|
|
var x = ~currentPadValues.x;
|
|
|
var y = ~currentPadValues.y;
|
|
var y = ~currentPadValues.y;
|
|
|
var pressure = ~currentPadValues.pressure;
|
|
var pressure = ~currentPadValues.pressure;
|
|
|
|
|
|
|
|
- // Update synthesis parameters but DON'T log every change to avoid spam
|
|
|
|
|
- switch(~currentPenType.asSymbol,
|
|
|
|
|
|
|
+ // 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 - Controls amplitude envelope
|
|
|
- \pen, {
|
|
|
|
|
|
|
+ "/pen", {
|
|
|
var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var ampAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var ampRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
|
- ~synthParams.ampAttack = ampAttack;
|
|
|
|
|
- ~synthParams.ampRelease = ampRelease;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\ampAttack, ampAttack);
|
|
|
|
|
+ ~setSynthsParam.(\ampRelease, ampRelease);
|
|
|
|
|
+
|
|
|
|
|
+ ["Amplitude envelope:", ampAttack, ampRelease].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Monoline - Controls filter envelope
|
|
// Monoline - Controls filter envelope
|
|
|
- \monoline, {
|
|
|
|
|
|
|
+ "/monoline", {
|
|
|
var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var filterAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var filterRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var filterRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
|
- ~synthParams.filterAttack = filterAttack;
|
|
|
|
|
- ~synthParams.filterRelease = filterRelease;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\filterAttack, filterAttack);
|
|
|
|
|
+ ~setSynthsParam.(\filterRelease, filterRelease);
|
|
|
|
|
+
|
|
|
|
|
+ ["Filter envelope:", filterAttack, filterRelease].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Marker - Controls pitch envelope
|
|
// Marker - Controls pitch envelope
|
|
|
- \marker, {
|
|
|
|
|
|
|
+ "/marker", {
|
|
|
var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
var pitchAttack = y.linexp(-0.5, 0.5, 0.001, 5);
|
|
|
var pitchRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
var pitchRelease = x.linexp(-0.5, 0.5, 0.001, 10);
|
|
|
|
|
|
|
|
- ~synthParams.pitchAttack = pitchAttack;
|
|
|
|
|
- ~synthParams.pitchRelease = pitchRelease;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\pitchAttack, pitchAttack);
|
|
|
|
|
+ ~setSynthsParam.(\pitchRelease, pitchRelease);
|
|
|
|
|
+
|
|
|
|
|
+ ["Pitch envelope:", pitchAttack, pitchRelease].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Pencil - Effect preset 1
|
|
// Pencil - Effect preset 1
|
|
|
- \pencil, {
|
|
|
|
|
- // Apply Preset 1 effects - with safety checks
|
|
|
|
|
- if(~filterSynth.notNil and: { ~filterSynth.isPlaying }, {
|
|
|
|
|
- ~filterSynth.set(
|
|
|
|
|
- \cutoff, x.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
- \res, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if(~lfoSynth.notNil and: { ~lfoSynth.isPlaying }, {
|
|
|
|
|
- ~lfoSynth.set(
|
|
|
|
|
- \freq, x.linlin(-0.5, 0.5, 0, 15),
|
|
|
|
|
- \intensity, pressure.linlin(1, 8, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if(~reverbSynth.notNil and: { ~reverbSynth.isPlaying }, {
|
|
|
|
|
- ~reverbSynth.set(
|
|
|
|
|
- \room, y.linlin(-0.5, 0.5, 0.1, 0.9)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ "/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 - Effect preset 2
|
|
|
- \crayon, {
|
|
|
|
|
- // Apply Preset 2 effects - with safety checks
|
|
|
|
|
- if(~lfoSynth.notNil and: { ~lfoSynth.isPlaying }, {
|
|
|
|
|
- ~lfoSynth.set(
|
|
|
|
|
- \freq, x.linlin(-0.5, 0.5, 15, 1),
|
|
|
|
|
- \intensity, x.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if(~delaySynth.notNil and: { ~delaySynth.isPlaying }, {
|
|
|
|
|
- ~delaySynth.set(
|
|
|
|
|
- \delaytime, x.linlin(-0.5, 0.5, 0.01, 1.0)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if(~filterSynth.notNil and: { ~filterSynth.isPlaying }, {
|
|
|
|
|
- ~filterSynth.set(
|
|
|
|
|
- \cutoff, y.linexp(-0.5, 0.5, 20, 18000),
|
|
|
|
|
- \res, pressure.linlin(1, 5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if(~reverbSynth.notNil and: { ~reverbSynth.isPlaying }, {
|
|
|
|
|
- ~reverbSynth.set(
|
|
|
|
|
- \mix, y.linlin(-0.5, 0.5, 0, 1)
|
|
|
|
|
- );
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ "/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)
|
|
// Fountain pen - Effect preset 3 (placeholder)
|
|
|
- \fountainPen, {
|
|
|
|
|
|
|
+ "/fountainPen", {
|
|
|
// Apply Preset 3 effects (TBD in documentation)
|
|
// Apply Preset 3 effects (TBD in documentation)
|
|
|
|
|
+ ["Fountain pen preset (TBD)"].postln;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// Water color - Effect preset 4 (placeholder)
|
|
// Water color - Effect preset 4 (placeholder)
|
|
|
- \waterColor, {
|
|
|
|
|
|
|
+ "/waterColor", {
|
|
|
// Apply Preset 4 effects (TBD in documentation)
|
|
// Apply Preset 4 effects (TBD in documentation)
|
|
|
|
|
+ ["Water color preset (TBD)"].postln;
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// ----- OSC Pad Values -----
|
|
|
|
|
|
|
+
|
|
|
|
|
+// ----- OSC Pad Vaues -----
|
|
|
// OSC responder for x coordinate
|
|
// OSC responder for x coordinate
|
|
|
OSCdef(\xOSC, { |msg, time, addr, port|
|
|
OSCdef(\xOSC, { |msg, time, addr, port|
|
|
|
var x = msg[1].asFloat;
|
|
var x = msg[1].asFloat;
|
|
@@ -289,11 +122,6 @@ OSCdef(\xOSC, { |msg, time, addr, port|
|
|
|
// Update current pad value and change effects
|
|
// Update current pad value and change effects
|
|
|
~currentPadValues.x = x;
|
|
~currentPadValues.x = x;
|
|
|
~changeEffectParams.value;
|
|
~changeEffectParams.value;
|
|
|
-
|
|
|
|
|
- // Handle touch movement if active
|
|
|
|
|
- if(~touchState.isActive, {
|
|
|
|
|
- ~handleTouchMove.value;
|
|
|
|
|
- });
|
|
|
|
|
|
|
|
|
|
}, '/aspectX');
|
|
}, '/aspectX');
|
|
|
|
|
|
|
@@ -304,137 +132,148 @@ OSCdef(\yOSC, { |msg, time, addr, port|
|
|
|
// Update current pad value and change effects
|
|
// Update current pad value and change effects
|
|
|
~currentPadValues.y = y;
|
|
~currentPadValues.y = y;
|
|
|
~changeEffectParams.value;
|
|
~changeEffectParams.value;
|
|
|
-
|
|
|
|
|
- // Handle touch movement if active
|
|
|
|
|
- if(~touchState.isActive, {
|
|
|
|
|
- ~handleTouchMove.value;
|
|
|
|
|
- });
|
|
|
|
|
|
|
|
|
|
}, '/aspectY');
|
|
}, '/aspectY');
|
|
|
|
|
|
|
|
-// OSC responder for pressure coordinate - THIS IS THE KEY ONE
|
|
|
|
|
|
|
+// OSC responder for pressure coordinate
|
|
|
OSCdef(\pressureOSC, { |msg, time, addr, port|
|
|
OSCdef(\pressureOSC, { |msg, time, addr, port|
|
|
|
var pressure = msg[1].asFloat;
|
|
var pressure = msg[1].asFloat;
|
|
|
|
|
|
|
|
// Update current pad value and change effects
|
|
// Update current pad value and change effects
|
|
|
~currentPadValues.pressure = pressure;
|
|
~currentPadValues.pressure = pressure;
|
|
|
~changeEffectParams.value;
|
|
~changeEffectParams.value;
|
|
|
-
|
|
|
|
|
- // Use smart trigger logic instead of always creating new synths
|
|
|
|
|
- ~smartTriggerSound.value;
|
|
|
|
|
|
|
|
|
|
}, '/pressure');
|
|
}, '/pressure');
|
|
|
|
|
|
|
|
-// ----- OSC Pen Types ----- (unchanged)
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// ----- OSC Pen Types -----
|
|
|
|
|
+// OSC responder for pen
|
|
|
OSCdef(\penOSC, { |msg, time, addr, port|
|
|
OSCdef(\penOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \pen;
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/pen');
|
|
}, '/pen');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for monoline
|
|
|
OSCdef(\monolineOSC, { |msg, time, addr, port|
|
|
OSCdef(\monolineOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \monoline;
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/monoline');
|
|
}, '/monoline');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for marker
|
|
|
OSCdef(\markerOSC, { |msg, time, addr, port|
|
|
OSCdef(\markerOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \marker;
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/marker');
|
|
}, '/marker');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for pencil
|
|
|
OSCdef(\pencilOSC, { |msg, time, addr, port|
|
|
OSCdef(\pencilOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \pencil;
|
|
|
|
|
- if(~initializePreset1.notNil, { ~initializePreset1.value; });
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
|
|
+ ~initializePreset1.value;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/pencil');
|
|
}, '/pencil');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for crayon
|
|
|
OSCdef(\crayonOSC, { |msg, time, addr, port|
|
|
OSCdef(\crayonOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \crayon;
|
|
|
|
|
- if(~initializePreset2.notNil, { ~initializePreset2.value; });
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
|
|
+ ~initializePreset2.value;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/crayon');
|
|
}, '/crayon');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for fountainPen
|
|
|
OSCdef(\fountainPenOSC, { |msg, time, addr, port|
|
|
OSCdef(\fountainPenOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \fountainPen;
|
|
|
|
|
- if(~initializePreset3.notNil, { ~initializePreset3.value; });
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
|
|
+ ~initializePreset3.value;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/fountainPen');
|
|
}, '/fountainPen');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for waterColor
|
|
|
OSCdef(\waterColorOSC, { |msg, time, addr, port|
|
|
OSCdef(\waterColorOSC, { |msg, time, addr, port|
|
|
|
var penType = msg[1].asFloat;
|
|
var penType = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
if (penType == 1.0) {
|
|
if (penType == 1.0) {
|
|
|
- ~currentPenType = \waterColor;
|
|
|
|
|
- if(~initializePreset4.notNil, { ~initializePreset4.value; });
|
|
|
|
|
|
|
+ ~currentPenType = msg[0].asString;
|
|
|
|
|
+ ~initializePreset4.value;
|
|
|
["Current pen type:", ~currentPenType].postln;
|
|
["Current pen type:", ~currentPenType].postln;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}, '/waterColor');
|
|
}, '/waterColor');
|
|
|
|
|
|
|
|
-// ----- OSC RGB Colors ----- (unchanged)
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// ----- OSC RGB Colors -----
|
|
|
|
|
+// OSC responder for red changes
|
|
|
OSCdef(\redOSC, { |msg, time, addr, port|
|
|
OSCdef(\redOSC, { |msg, time, addr, port|
|
|
|
var component = msg[1].asFloat;
|
|
var component = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
|
|
+ // Update current color
|
|
|
~currentColor.r = component;
|
|
~currentColor.r = component;
|
|
|
- ~synthParams.redAmt = component;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\redAmt, component);
|
|
|
|
|
+
|
|
|
["Color changed:", ~currentColor].postln;
|
|
["Color changed:", ~currentColor].postln;
|
|
|
}, '/r');
|
|
}, '/r');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for green changes
|
|
|
OSCdef(\greenOSC, { |msg, time, addr, port|
|
|
OSCdef(\greenOSC, { |msg, time, addr, port|
|
|
|
var component = msg[1].asFloat;
|
|
var component = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
|
|
+ // Update current color
|
|
|
~currentColor.g = component;
|
|
~currentColor.g = component;
|
|
|
- ~synthParams.greenAmt = component;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\greenAmt, component);
|
|
|
|
|
+
|
|
|
["Color changed:", ~currentColor].postln;
|
|
["Color changed:", ~currentColor].postln;
|
|
|
}, '/g');
|
|
}, '/g');
|
|
|
|
|
|
|
|
|
|
+// OSC responder for blue changes
|
|
|
OSCdef(\blueOSC, { |msg, time, addr, port|
|
|
OSCdef(\blueOSC, { |msg, time, addr, port|
|
|
|
var component = msg[1].asFloat;
|
|
var component = msg[1].asFloat;
|
|
|
|
|
+
|
|
|
|
|
+ // Update current color
|
|
|
~currentColor.b = component;
|
|
~currentColor.b = component;
|
|
|
- ~synthParams.blueAmt = component;
|
|
|
|
|
|
|
+ ~setSynthsParam.(\blueAmt, component);
|
|
|
|
|
+
|
|
|
["Color changed:", ~currentColor].postln;
|
|
["Color changed:", ~currentColor].postln;
|
|
|
}, '/b');
|
|
}, '/b');
|
|
|
|
|
|
|
|
-// Cleanup function
|
|
|
|
|
-~cleanupOSCSystem = {
|
|
|
|
|
- // End any active touch
|
|
|
|
|
- ~handleTouchEnd.value;
|
|
|
|
|
-
|
|
|
|
|
- // Clean up all synths
|
|
|
|
|
- ~activeSynths.keysValuesDo({ |key, synth|
|
|
|
|
|
- synth.set(\gate, 0);
|
|
|
|
|
- });
|
|
|
|
|
- ~activeSynths.clear;
|
|
|
|
|
-
|
|
|
|
|
- // Reset touch state
|
|
|
|
|
- ~touchState.isActive = false;
|
|
|
|
|
- ~touchState.currentSynth = nil;
|
|
|
|
|
-
|
|
|
|
|
- "OSC system cleaned up".postln;
|
|
|
|
|
-};
|
|
|
|
|
|
|
|
|
|
-// Register cleanup with CmdPeriod
|
|
|
|
|
-CmdPeriod.add({
|
|
|
|
|
- ~cleanupOSCSystem.value;
|
|
|
|
|
-});
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// Start the OSC server on port 57120 (default SuperCollider port)
|
|
// Start the OSC server on port 57120 (default SuperCollider port)
|
|
|
thisProcess.openUDPPort(57120);
|
|
thisProcess.openUDPPort(57120);
|
|
|
-"OSC server ready on port 57120 - FIXED FOR TOUCH MANAGEMENT".postln;
|
|
|
|
|
-"Now only creates synths on touch BEGIN, updates on MOVE, releases on END".postln;
|
|
|
|
|
|
|
+"OSC server ready on port 57120".postln;
|
|
|
|
|
+"Registered OSC commands: /touch, /pen, /color".postln;
|
|
|
"Ready to receive data from iDraw OSC app".postln;
|
|
"Ready to receive data from iDraw OSC app".postln;
|
|
|
-"To cleanup system, run: ~cleanupOSCSystem.value".postln;
|
|
|
|
|
)
|
|
)
|