Extensive OSC tutorial

@samaaron

I actually can’t find any info on multiple different machine incoming osc messages in the Ruby language. Do I have to rethink how to get multiple osc messages from different devices?

Buy a different wifi module instead of the wemos D1 mini

when you receive an osc message from a particular device it looks like
/osc:192.168.1.56:4560/cutoff for example if it is sent from a device with ip address 192.168.1.56 Normally you are not interested in the ip address of the sending device, and you can use a statement like
data = sync "/osc*/cutoff" to receive and extract the data. If however you want to differentiate between different devices you can sync on the entire input and use
data = sync "/osc:192.168.1.56:4560/cutoff"
This will ONLY sync to an osc command sent from that particular ip address. As Sam suggested earlier you could have a separate live_loop for each of your required OSC messages. maybe even 15 in total with 5 for each separate device.
Once you have the data, how you use it depends on what you want to control.
I’ll add a further post with some examples of controlling fx parameters with osc inputs tomorrow.

I’ll wait but from my knowledge so far (and that’s not much :sweat_smile:)
The sound of a live_loop won’t play without the OSC message coming in.

And I need the sound to be constantly playing from the moment I start it. And the OSC should only change the parameters.

Again I want to show my appreciation of your help @samaaron too, because every time it gets a little easier to understand how to work with the code and makes me keep coming back to realize my projects!

Here as promised is one example in which three osc commands independently control three parameters of sounding notes in a live loop. You could alternatively have one very long (even an hour) note using a fixed synth and control the parameters of that note such as pitch, volume, pan value using osc inputs. Let me know if you would like to see such an example. Wasn’t sure what you meant by continous sound.

use_osc "localhost",4560

#three osc messages. Normally sent from your hardware device
osc "/amp",0.4
osc "/cutoff",120
osc "/synth","saw" #you could use numbers and a lookup list to get the name of the synth instead

#three live loops to read the osc messages and get their data
#data is stored using set commands. The values are retireve dusing get commands in the test liveloop
live_loop :rx1 do
  use_real_time
  val = sync "/osc:127.0.0.1:4560/cutoff"
  puts val[0]
  set :lp,val[0]
end

live_loop :rx2 do
  use_real_time
  val = sync "/osc:127.0.0.1:4560/amp"
  puts val[0]
  set :vol,val[0]
end

live_loop :rx3 do
  use_real_time
  val= sync  "/osc:127.0.0.1:4560/synth"
  set :synthname,val[0]
end

#test live loop that plays a stream of ntoes with synth, volume and synth set by the osc commands
live_loop :test do
  cutoff=get(:lp)
  vol=get(:vol)
  synthname=get(:synthname)
  synth synthname,note: rrand_i(50,100),release: 0.2,cutoff: cutoff,amp: vol
  sleep 0.2
end

The osc commands could be sent from different ip addresses, in which case the rx liveloops would contain the relevant ip address as part of the sync string. They will always have to be port 4560 to work as Sonic Pi cues. You can extend the number of osc inputs and use several ip addresses together. If you dont care or need to separate which address they come from you can use sync “/osc*/cutoff” etc.

In the example above, you can change the values sent by the osc commands and re-run whenever you want. Your hardware may use rotary knobs or sliders to change values sent, in which case you may need to scale them.

2 Likes

Very good example @robin.newman. Thanks for your help !

One thing that may be useful is that wherever you use sync you can also use get.

So, instead of needing multiple live loops (:rx1, :rx2, :rx3) that are explicitly syncing on an incoming OSC message and then setting another time state entry such as (:lp, :vol, :synthname) with the incoming values, you can just call get["/osc:127.0.0.1:4560/synth"] directly and just need one live loop:

live_loop :test do
  co = get("/osc:127.0.0.1:4560/cutoff")[0]
  vol = get("/osc:127.0.0.1:4560/amp")[0]
  syn = get("/osc:127.0.0.1:4560/synth")[0]
  synth syn, note: rrand_i(50,100), release: 0.2, cutoff: co, amp: vol
  sleep 0.2
end
3 Likes

Hi @robin.newman

I’m using this.

use_osc "localhost",4560

#three osc messages. Normally sent from your hardware device
#osc "/mq4"
#osc "/cutoff",120
#osc "/synth","saw" #you could use numbers and a lookup list to get the name of the synth instead

#three live loops to read the osc messages and get their data
#data is stored using set commands. The values are retireve dusing get commands in the test liveloop
live_loop :rx1 do
  use_real_time
  val = sync "/osc:127.0.0.1:4560/mq4"
  puts val[0]
  set :lp,val[0]
end

live_loop :rx2 do
  use_real_time
  val = sync "/osc:127.0.0.1:4560/mq8"
  puts val[0]
  set :vol,val[0]
end

live_loop :rx3 do
  use_real_time
  val= sync  "/osc:127.0.0.1:4560/mq4"
  set :synthname,val[0]
end

#test live loop that plays a stream of ntoes with synth, volume and synth set by the osc commands
live_loop :test do
  cutoff=get(:lp)
  vol=get(:vol)
  synthname=get(:synthname)
  synth synthname,note: rrand_i(50,100),release: 0.2,cutoff: cutoff,amp: vol
  sleep 0.2
end 

And I get osc messages in sonic pi but I don’t hear or see anything altering due to the incoming messages…

What I’m I still doing wrong?

Looks like you are sending from an external device. change the osc sync lines to
from
val = sync "/osc:127.0.0.1:4560/mq4"
to
val= = sync "/osc*/mq4"
and simlarly for the other one.
val = sync "/osc*/mq8
This means they will respond to input from any ip address sending a message to /mq4