Using Orca to control Sonic Pi with OSC

I’ve been experimenting with using the live coding MID/OSC sequencer tool Orca to sequence synths and control parameters in Sonic Pi. If you haven’t seen Orca before, it’s a very neat visual programming environment for sending MIDI and OSC commands. I’m just getting started with it, but already I think it’s a really nice complement to Sonic Pi for creating and performing computer-based music.

In the first example, Orca is sequencing two Sonic Pi synths via MIDI, as well as sequencing changes to synth and fx parameters via OSC.

In the next two examples, Orca is sending MIDI to an external synthesizer, whose audio is then routed to my computer’s audio interface. In Sonic Pi, I have three recording buffers and three loopers to sample and playback the incoming audio. The recording buffers and loopers are again controlled by Orca using OSC. In these videos, the audio is then being sent to an external reverb unit.


Has anyone else tried using Orca with Sonic Pi? These are my first attempts at using OSC, so any suggestions or feedback is greatly appreciated!

EDIT: Code from first example added to github

3 Likes

Thanks for your examples, which I’ve seen on your tweets. They insipred me to get going and I have been playing with ORCA for the last few days getting to grips with it. I have worked with both midi and osc output, but noting earth shattering yet :slight_smile: As you say it sits nicely with Sonic Pi.
The only thing I haven’t sussed yet is the & command which is supposed to get midi input back into ORCA. Not sure how to get that going. Otherwise worked through youtube vids from Allieway, although some of these use an earlier version of ORCA where the inputs were on one side of the command letter, rather than on each side as now, so her examples need a bit of tweaking to get going.

EDIT As a matter of interest what external synth did you use for the second example?

Cool. I like these sounds a lot :smiley: . Hopefully I will have some time near to have a look at Orca and your code.

Yeah, I haven’t tried using the & operator yet. Honestly, I feel like I have barely scratched the surface, when it comes to all the operators and sequencing possibilities.

I’m using the VolcaFM from Korg. Great little fm synth. Very easy to load up with DX7 patches :slight_smile:

I’m also playing a lot with ORCA these days. Really a great sequencer. I haven’t tried so much to interface something with Sonic-Pi so far but I know that Neauoire, the dev behind ORCA really tried to make it easy to use both at the same time.

1 Like

Hi @mattholamieux

i’ve seen your videos yesterday : great work and i’ve installed orca on my linux machine.
Thank you for sharing the code with us.
Just a question how to send many parameters in orca via osc ? Or let us know which block is used to target this goal in your example 1

edit : well i find

Maybe it would worth to make a video about your work and explain the commands you type, no ?

ps : for french people, il y a cette vidéo d’introduction très bien faite pour se lancer avec ORCA http://makingsound.fr/blog/orca-sequenceur-modulaire/

@nlb I’ve just typed in the first video example into ORCA and Sonic Pi and it is working well.
In answer to your question you send an OSC command by “banging” a sequence like

*=v135ce47

= means send OSC message, the next byte is the osc address eg /v and the following bytes are sent in a list. * is the bang arriving to send the message.
This will send out an osc message addressed to the first character ie /v
Using the Mac version of ORCA you select the destination port for Sonic Pi on the local machine (4559) from the OSC menu

In sonic pi 3 the OSC message will arrive as /osc/v
you can receive it using a live loop such as

live_loop :oscIn do
  use_real_time
  v = sync "/osc/v"
  puts v #received data list
  puts v[0]
  puts v[1]
  puts v[2]
  puts v[3]
  puts v[4]
  puts v[5]
  puts v[6]
end

This outputs

  ├─ [1, 3, 5, 12, 14, 4, 7]
 ├─ 1
 ├─ 3
 ├─ 5
 ├─ 12
 ├─ 14
 ├─ 4
 └─ 7

You can then scale the single byte values received as required, and use them to control various values.

Hope this helps.

2 Likes

@mattholamieux I typed in the first example from the video, and it works well.
I like the way that you queued up two OSC messages using successive syncs and in the same live_loop then synced the arriving midi note. A neat way to make sure everything is set up in the correct sequence.
I think others might appreciate it if you added the code for this example to your gist, especially as it runs on Sonic Pi without any external synths which some may not have.

I do find that very occasionally I get a weird sound from this example, Something goes awry and there seems to be a lot of white noise. did you find this? I’m checking the code as it is very easy to miss something on ORCA!!!

@robin.newman Sorry for not including the code for the first example! You should be able to find it now on the github page here.

In terms of the unwanted/unexpected noise, is it a result of the bitcrusher fx? In my example, the mix and bits params are being randomized pretty excessively :slight_smile:

@nlb From the screenshot you shared, it looks like you are doing everything correct in Orca to send multiple OSC parameters. Make sure you have Sonic Pi selected as the OSC destination from the OSC menu in Orca. Once you have Orca sending OSC to Sonic Pi, you should see those messages arriving in Sonic Pi in the cue log.

@robin.newman has given a very thorough explanation of how to receive and parse those OSC messages in Sonic Pi. Let me know if you’re able to get it working. If not, I’d be happy to explain a bit more.

Hi

Under Linux, the osc port used by ORCA changes it’s not only /osc/
My example introduces the Q operator.

305Q means Q query.
The 3 is to say the values are after 3 position on the right. we put # to tell orca that is not some commands but some values. # is used to put in comment.
then the 0 is you guess the first line and 5 to say you have 5 values to query and to return under the letter Q.
So if you change 0 to 1, it will return v2212' So if you change 0 to 2, it will returnv1114’

then we send osc message with the = operator
to put some random we use the R operator who accept a left value and a right value to set value return 0, 1, 2.

1 Like

Don’t forget that there is a companion app for ORCA to create complex UDP / OSC messages : AIOI. This may be the best thing to do to use Sonic-Pi with ORCA.

1 Like

Yep! I’ve only spent a few minutes with AIOI, but it was pretty easy to set up and seems very handy (especially for sending floats).

Just thought I’d share one more Orca + Sonic Pi video. This is another one where Sonic Pi is used for live sampling and playback of an external synth sequenced by Orca.


use_bpm 60
T= 1.0


### MASTER ###

live_loop :master do
  v = sync "/osc/h"
  set_mixer_control! amp: v[0], amp_slide: v[1], lpf: v[2]*10, lpf_slide: v[3]
end

### LIVE AUDIO ###

live_loop :audio_in do
  use_real_time
  v = sync "/osc/g"
  a = v[0]
  b = v[1]
  c = v[2]
  d = v[3]
  e = v[4]
  f = v[5]
  g = v[6]
  h = v[7]
  i = v[8]
  j = v[9]
  k = v[10]
  with_fx :level, amp: k do
    with_fx :reverb, mix: a/10.0, room: b/10.0, damp: c/10.0 do
      with_fx :echo, mix: d/10.0, phase: e/4.0, decay: f do
        with_fx :bitcrusher, mix: g/10.0, bits: h, sample_rate: i*1000, cutoff: j*10 do
          with_fx :panslicer, mix: 1, phase: 4, wave: 2, smooth: 0.15 do
            live_audio :chan1, input: 2
          end
        end
      end
    end
  end
end

###RECORDERS###

live_loop :recorder1 do
  use_real_time
  v = sync "/osc/a"
  set :buff_len1, v[0]
  print "RECORDING BUFFER ONE, LEN: " + v[0].to_s + " CHAN: " + v[1].to_s
  with_fx :level, amp: 0 do
    with_fx :record, buffer: buffer(:buff_one, v[0]), pre_mix: 0, pre_mix_slide: 0.1 do |e|
      control e, pre_mix: 1
      live_audio :mic, input: v[1]
      sleep T*v[0]-0.1
      control e, pre_mix: 0
    end
  end
end

live_loop :recorder2  do
  use_real_time
  v = sync "/osc/b"
  set :buff_len2, v[0]
  print "RECORDING BUFFER TWO, LEN: " + v[0].to_s + " CHAN: " + v[1].to_s
  with_fx :level, amp: 0 do
    with_fx :record, buffer: buffer(:buff_two, v[0]), pre_mix: 0, pre_mix_slide: 0.1 do |e|
      control e, pre_mix: 1
      live_audio :mic, input: v[1]
      sleep T*v[0]-0.1
      control e, pre_mix: 0
    end
  end
end

live_loop :recorder3 do
  use_real_time
  v = sync "/osc/c"
  set :buff_len3, v[0]
  print "RECORDING BUFFER THREE, LEN: " + v[0].to_s + " CHAN: " + v[1].to_s
  with_fx :level, amp: 0 do
    with_fx :record, buffer: buffer(:buff_three, v[0]), pre_mix: 0, pre_mix_slide: 0.1 do |e|
      control e, pre_mix: 1
      live_audio :mic, input: v[1]
      sleep T*v[0]-0.1
      control e, pre_mix: 0
    end
  end
end

###LOOPERS###

live_loop :looper1 do
  v = sync "/osc/d"
  a = get[:buff_len1]
  b = v[0]
  c = v[1]
  d = v[2]
  f = v[3]
  h = v[4]
  i = v[5]
  j = v[6]
  k = v[7]
  g = v[8]
  l = v[9]
  buff = :buff_one
  with_fx :pitch_shift, mix: h/10.0, pitch: i, window_size: j/4.0 do
    sample buffer(buff, a), rate: b/4.0, rpitch: c, start: d/35.0, finish: f/35.0, amp: g if one_in(l)
  end
end

live_loop :looper2 do
  v = sync "/osc/e"
  a = get[:buff_len2]
  b = v[0]
  c = v[1]
  d = v[2]
  e = v[3]
  h = v[4]
  i = v[5]
  j = v[6]
  k = v[7]
  l = v[9]
  g = v[8]
  buff = :buff_two
  with_fx :pitch_shift, mix: h/10.0, pitch: i, window_size: j/4.0 do
    sample buffer(buff, a), rate: b/4.0, rpitch: c, start: d/35.0, finish: e/35.0, attack: 0.05, decay: 0.05, amp: g if one_in(l)
  end
end

live_loop :looper3 do
  v = sync "/osc/f"
  a = get[:buff_len3]
  b = v[0]
  c = v[1]
  d = v[2]
  e = v[3]
  g = v[7]
  l = v[8]
  h = v[4]
  i = v[5]
  j = v[6]
  slice_idx = (range d,e).tick
  slice_size = 0.0625
  s = slice_idx * slice_size
  st = s + slice_size
  buff = :buff_three
  with_fx :pitch_shift, mix: h/10.0, pitch: i, window_size: j/4.0, pitch_dis: 0.001, time_dis: 0.001 do
    sample buffer(buff, a), start: s, finish: st, rate: b/4.0, rpitch: c, attack: 0.05, release: 0.05, amp: g, pan: rrand(-1,1) if one_in(l)
  end
end


2 Likes

Thanks so much for all this info and examples. I was finally able to set up Orca with SonicPi and thought these “getting started” steps might help, too.

I installed “loopMIDI” so I can route MIDI on my Windows machine. In loopMIDI I added a basic channel called loopmidi_port.

In SonicPi I enabled MIDI subsystems and OSC server. In Orca I set MIDI to “LoopMIDI Port Output” and OSC to “SonicPi(4559)”.

Now I can send both MIDI and OSC to SonicPi from Orca. As you start sending messages, they’ll appear in the Cue logs.

First message:

  • Add a D to kick out a bang
  • From the bang send MIDI message: :02c

Now this will appear in the SonicPi logs as: /midi/loopmidi_port/0/1/note_on [56, 119]

In SonicPi we can listen for it with a simple live_loop like this:

live_loop :meedee do
  use_real_time
  note, velocity = sync "/midi/loopmidi_port/0/1/note_on"
  play note, amp: velocity/127.0
end

Notice that as we receive the message it’s broken down into note and velocity, then passed directly to a SonicPi play.

For OSC we don’t, inherently, get a note and velocity but we can send any values we want. So you can copy the bang from the Orca D with an Orca T and use it to bang the OSC send command =vff

Not we’ll see the OSC message show up in the SonicPi cue logs:

/osc/v [15, 15]

We can now use that OSC message to trigger anything we want. Adding a bass drum:

live_loop :ohesssee do
  use_real_time
  velocity, rate = sync "/osc/v"
  sample :bd_haus, rate: rate/16.0+0.1, amp: velocity/16.0
end

Sorry to just tack on to this thread but it started me thinking I should try Orca+SonicPi and I was pleasantly surprised how easy it is. Hope this helps someone else who lands here!

2 Likes

Hi @funwhilelost

About OSC port in Sonic Pi, the next version will receive data on 4560 port no more on 4559. If you build the spi 3.2dev from sources, don’t forget it !
So you will have to use osc command in Orca to specify the osc port
ctrl + k then type osc:4560

1 Like