// osc_receiver.scd - OSC receiver for webapp // Run this in SuperCollider: sclang supercollider/osc_receiver.scd // Then click nodes in the webapp to play tones s.boot; ( s.waitForBoot { // Store reference to current synth and frequency var currentSynth = nil; var currentFreq = nil; // Define synth on the server with ASR envelope // Note: doneAction is 0 (no auto-free) - we manage release manually SynthDef(\sineTone, { |freq = 440, amp = 0.25, gate = 1| var env = EnvGen.kr( Env.adsr(2, 3, 0.5, 3), gate, doneAction: 0 // Don't auto-free - we'll release manually ); Out.ar(0, SinOsc.ar(freq) * env * amp); }).add; // Wait for synth to be added to server s.sync; // OSC handler for /freq messages - explicitly bind to port 57120 ~oscHandler = OSCFunc({ |msg, time, addr, recvPort| if (msg.size >= 3, { var freq = msg[2].asFloat; if (freq > 0, { // Check if this is the same frequency - just release if (currentSynth.notNil and: { currentFreq == freq }, { currentSynth.set(\gate, 0); currentSynth = nil; currentFreq = nil; }, { // Different frequency - release old, create new if (currentSynth.notNil, { currentSynth.set(\gate, 0); }); currentSynth = Synth(\sineTone, [\freq, freq, \amp, 0.25]); currentFreq = freq; }); }); }); }, '/freq', nil, 57120); "OSC receiver ready on port 57120".postln; "Click nodes in webapp to play".postln; // Keep alive while { true } { 10.wait; }; } )