bnc
bnc

Reputation: 57

Python-osc message sending to SuperCollider

How do I send FFT information of phases and amplitudes to an oscillator bank in SuperCollider? It seems that I've misunderstood something but can't figure out what is wrong in my code:

    msg = osc_message_builder.OscMessageBuilder(address = "/s_new 100 1 1 oscBank512")
    msg.add_arg(" amplitude ", amplitudes)
    msg.add_arg(" phase ",phases)
    msg.add_arg(" attackSynth ", 0.1)
    msg.add_arg(" releaseSynth", 0.5)
    msg = msg.build()
    client.send(msg)

So my oscillator bank has 256 SinOscs and I'd want to send that amplitude and phase information for them, they are in those arrays(amplitudes, phases). However python-osc doesn't allow me to do that. It says:

ValueError: arg_type must be one of ('f', 'i', 'b', 's', 'T', 'F')

So how would I construct that OSC message properly? Python-osc tutorial is really minimal and couldn't find any help online. I'd use pyOSC or OSC but pip wasn't able to install them so I'm stuck with python-osc.

SuperCollider code for the oscillator bank:

    SynthDef.new(\oscBank512, {
    arg attackSynth=0.1, releaseSynth=0.1;
    var dmplitudeReceive = \dmplitudeReceive.kr( 0.0!256 );
    var phaseReceive = \phaseReceive.kr( 0.0!256 );
    var osc1, envelopeSynth, sig, amp, freq, phases, amps,out;

    freq = Array.fill(256, {
        arg i, j=(22050/256), k=(j/2);
        if(i==0){i*j}{(i*j)-k};
    });
    amp = EnvGen.kr(
            envelope: Env.perc(
                attackTime: attackSynth,
                releaseTime: releaseSynth,
                level: 1,
                curve: -4),
            doneAction: 2);

    sig = SinOsc.ar(freq:freq,  mul: dmplitudeReceive, phase: phaseReceive);
    sig = sig*amp;
    sig = Limiter.ar(in:Mix.new(sig), level:1);


    Out.ar(0, Pan2.ar(sig));
}).add;

The dmplitudeReceive is named with d on purpose.

Upvotes: 0

Views: 2167

Answers (2)

Charles Martin
Charles Martin

Reputation: 358

The address in this message should be just "/s_new", everything else is a separate argument. The keys and values go into the message sequentially and SuperCollider should be able to sort them out.

This code adds in the argument one at a time with their type. I would have thought that each amplitude and phase would have a different name in your synthdef that you would have to address separately. If not, they might end up with a different integer index that you can address.

from pythonosc import osc_message_builder
from pythonosc import udp_client

client = udp_client.SimpleUDPClient('localhost', 57110)

amplitude = 0.5 # just adding one amplitude
phase = 0.5 # just adding one phase

msg = osc_message_builder.OscMessageBuilder(address = '/s_new')
msg.add_arg(100, arg_type='i')
msg.add_arg(1, arg_type='i')
msg.add_arg(1, arg_type='i')
msg.add_arg('oscBank512', arg_type='s')
msg.add_arg('amplitude', arg_type='s')
msg.add_arg(amplitude, arg_type='f')
msg.add_arg('phase', arg_type='s')
msg.add_arg(phase, arg_type='f')
msg.add_arg('attackSynth', arg_type='s')
msg.add_arg(0.1, arg_type='f')
msg.add_arg('releaseSynth', arg_type='s')
msg.add_arg(0.5, arg_type='f')
msg = msg.build()
client.send(msg)

Unfortunately python-osc doesn't support the array type for OSC messages which SuperCollider uses to send arrays of arguments to the synthesis server. I'm not aware of a Python OSC library that does support arrays in messages, so you might have to think of another way to achieve what you want.

One option might be to have a much simpler synthdef with one oscillator and generate 256 of them (or more!) as needed. That way you don't have to try to send 256 values when creating one synthdef.

Upvotes: 1

Dan Stowell
Dan Stowell

Reputation: 4758

Look at the arguments to the add_arg function: arg_value, arg_type=None. You're trying to add a "key" and a "value" but there's no way to add a "key".

You simply have to add the values "anonymously". When you receive them, you decode them by knowing which order you added them.

Upvotes: 0

Related Questions