OSC to SuperCollider
Example directory (scamp): examples/Tutorial/24_osc_to_supercollider
Download: 24_osc_to_supercollider.zip
Playing back notes by sending OSC messages to the SuperCollider, which receives them and spawns Synths in response. Start SuperCollider and run the code blocks in receive_from_supercollider.scd, then run osc_to_supercollider.py. Note that the easy way to receive note events from SCAMP in SuperCollider specifically is with the ScampUtils quark, as demonstrated by receive_from_supercollider_scamputils.scd.
Topics: Playback › Playback implementations
from scamp import *
import random
random.seed(42)
s = Session()
# on the other end, an OSC receiver is setup to play notes that take vibrato and OSC messages as well as the usual
vib = s.new_osc_part("vibrato", 57120)
s.start_transcribing()
# any property entries starting or ending with "param" will be treated as extra playback parameters
while s.beat < 20:
note_length = random.uniform(0.3, 3)
# glissando between three random values
pitch_env = [random.randint(60, 82) for _ in range(3)]
volume_env = random.choice([
# percussive envelope
Envelope.ar(0.1, note_length - 0.1),
# fp crescendo envelope
Envelope([1, 0.2, 1], [0.1, note_length - 0.1], curve_shapes=[-2, 3])
])
vib_width_env = [random.uniform(0, 5) for _ in range(2)]
vib_freq_env = [random.uniform(3, 13) for _ in range(2)]
vib.play_note(
pitch_env, volume_env, note_length,
{"param_vibWidth": vib_width_env,
"param_vibFreq": vib_freq_env},
blocking=False
)
wait(random.uniform(0.5, 3))
wait_for_children_to_finish()
performance = s.stop_transcribing()
engraving_settings.max_voices_per_staff = 1
performance.to_score(max_divisor=6, simplicity_preference=3).show()
receive_from_supercollider.scd
// --------------------------------------------------------------------------------------------------
// Corresponding SuperCollider Code for OSC-to-SuperCollider SCAMP example. Run this before the Python
// script by booting the server and then running the code blocks below in order.
// --------------------------------------------------------------------------------------------------
// If it's not working, make sure the port printed here matches the port that the Python file is sending to
NetAddr.langPort.postln;
(
// ----------------------------- 1) Define vib synth ----------------------------------
SynthDef(\vibSynth, { |out=0, freq=440, gain=0.1, vibFreq=20, vibWidth=0.5, gate=1|
var envelope = EnvGen.ar(Env.asr(releaseTime:0.5), gate, doneAction: 2);
var vibHalfSteps = SinOsc.ar(vibFreq) * vibWidth;
var vibFreqMul = 2.pow(vibHalfSteps / 12);
var vibSine = SinOsc.ar(freq * vibFreqMul) * gain;
Out.ar(out, (envelope * vibSine / 5) ! 2);
}, [\ir, 0.1, 0.1, 0.1, 0.1, \kr]).add;
)
(
// ---------------------------- 2) Set up OSC Receivers -------------------------------
// This dictionary maps the note-id's sent by SCAMP to their associated Synths
~notesPlaying = Dictionary();
// START NOTE
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1], pitch = msg[2], volume = msg[3];
// Start a new Synth and place it in the ~notesPlaying dictionary under its associated id
~notesPlaying.put(id, Synth(\vibSynth,
[\freq, pitch.midicps,
\gain, (-40 * (1-volume)).dbamp]
));
}, '/vibrato/start_note');
// END NOTE
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1];
~notesPlaying[id].set(\gate, 0);
}, '/vibrato/end_note');
// CHANGE PITCH
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1], pitch = msg[2];
~notesPlaying[id].set(\freq, pitch.midicps);
}, '/vibrato/change_pitch');
// CHANGE VOLUME
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1], volume = msg[2];
~notesPlaying[id].set(\gain,
(-40 * (1-volume)).dbamp);
}, '/vibrato/change_volume');
// CHANGE VIBRATO FREQUENCY
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1], freq = msg[2];
~notesPlaying[id].set(\vibFreq, freq);
}, '/vibrato/change_parameter/vibFreq');
// CHANGE VIBRATO WIDTH
OSCFunc({ arg msg, time, addr, recvPort;
var id = msg[1], width = msg[2];
~notesPlaying[id].set(\vibWidth, width);
}, '/vibrato/change_parameter/vibWidth');
)
receive_from_supercollider_scamputils.scd
// --------------------------------------------------------------------------------------------------
// Corresponding SuperCollider Code for OSC-to-SuperCollider SCAMP example. Run this before the Python
// script by booting the server and then running the code blocks below in order.
// --------------------------------------------------------------------------------------------------
// If it's not working, make sure the port printed here matches the port that the Python file is sending to
NetAddr.langPort.postln;
(
// ----------------------------- 1) Define vib synth ----------------------------------
ScampUtils.instrumentFromSynthDef(
SynthDef(\vibSynth, { |out=0, freq=440, volume=0.1, vibFreq=20, vibWidth=0.5, gate=1|
var envelope = EnvGen.ar(Env.asr(releaseTime:0.5), gate, doneAction: 2);
var vibHalfSteps = SinOsc.ar(vibFreq) * vibWidth;
var vibFreqMul = 2.pow(vibHalfSteps / 12);
var vibSine = SinOsc.ar(freq * vibFreqMul) * volume;
Out.ar(out, (envelope * vibSine / 5) ! 2);
}, [\ir, 0.1, 0.1, 0.1, 0.1, \kr]);
)
)