Chords with osc

Hi

This post https://in-thread.sonic-pi.net/t/sending-generated-notes-as-osc-int/ ends me up to try to send chord via OSC and then play the chord received.

It seems to work but not sure the code is very very good… Note that i meet an issue as the tempo is very hazardous. So kings of code, is you can test this, i will appreciate.

use_bpm 120

live_loop :sendChordsNotesViaOSC do
  ##| stop
  
  notes = chord :c, :madd11
  
  # we get a ring
  puts notes
  
  ##| play_chord notes
  ##| sleep 4
  
  ##| notes.each do | n |
  ##|   osc "/foo/notes", n
  ##| end
  
  # we can' send a ring via osc maybe using an array ?
  
  tab = Array.new
  notes.each_with_index do |n, idx|
    tab[idx] = n
  end
  ##| puts tab

  
  ##| So no this does not work with array
  ##| osc "/foo/notes", tab
  
  ## so we send a string, each note separated by a space to split this string at the reception
  puts notes_sent = notes.join(" ")
  osc "/foo/notes", notes_sent
  
  # just send a amp integer value
  osc "/foo/notes/amp", [0.5, 1, 2].tick
  sleep 4
end



live_loop :player do
  use_real_time
  msg = sync "/osc*/foo/notes"
  # we get a string
  puts msg[0]
  
  # but play_chord wants an array...
  # So how can i rebuilt an array from the string ?
  foo = msg[0].split
  puts foo
  
  # but we need to convert into an integer
  goo = Array.new
  foo.each_with_index do |s, k|
    goo[k]=s.to_i
  end
  puts goo
  
  arrayNotes = [:c, :e, :a, :c5, :d5]
  
  vol = sync "/osc*/foo/notes/amp"
  synth :dsaw, attack: 0, amp: vol[0], notes: goo
#  synth :dsaw, attack: 0, amp: vol[0], notes: arrayNotes
end

My reply there should give you at least a clue :wink:
The tricky bit however, is that if you want to send multiple values from a ring or array as a single parameter to osc, (rather than passing the osc function multiple data parameters as I describe in that thread) you need to lean into a trick of plain old Ruby: the splat operator :slight_smile:
So the line would become something like:

osc "/foo/notes", *(chord :a3, :minor)

(Note the *)
There’s plenty of further information around on the splat operator if needed:
See An introduction to Ruby’s *Splat and double **Splat operators for an example :slight_smile:

At the other end, to play back the chord, you could do something like:

  notes = sync "/osc*/foo/notes"
  synth :prophet, note: notes

ah ah maybe i should have ask before but no i will remember
You guess that i ignored this magical splat operator :slight_smile:

So this is a shorty version

# Splat version thanks to Ethan :-)
# A shorty solution 

use_osc "localhost", 4560
use_osc_logging false
use_debug false

use_bpm 120

live_loop :sendChordsNotesViaOSC do
  use_real_time 
  notes = chord :c, :madd11
  osc "/foo/notes", *notes
  
  # just send a amp integer value
  osc "/foo/notes/amp", [0.5, 1, 2].tick
  sleep 1
end

live_loop :player do
  use_real_time
  n = sync "/osc*/foo/notes"
  vol = sync "/osc*/foo/notes/amp"
  synth :dsaw, attack: 0, amp: vol[0], notes: n  
end

EDIT : add use_real_time fix the issue :slight_smile:

But still have the issue : this is not regular…

Can you explain what you mean by not regular? :slight_smile:

the chords are not played at the tempo given by the sleep 1

Ah.
I hear an occasional silence as the chord sometimes doesn’t play for a beat.
If you add use_real_time to the :sendChordsNotesViaOSC loop, then it seems to me to play the chord every beat as expected. Does that help?

of course it does :slight_smile: Thanks

1 Like