sonic-pi icon indicating copy to clipboard operation
sonic-pi copied to clipboard

OSC message lost

Open slvlirnoff opened this issue 6 years ago • 7 comments

Hello,

While trying to record midi note_on/off event I see that some time (when pressing simultaneous notes) I loose some one (or more) of them while the note_on event is properly received and displayed in the console.

The event properly display in the "signal" log but is never 'synced'. I've tried to reproduce the issue using only OSC messages using the code below.

sleep 1
live_loop :read_osc do
  use_real_time
  n = sync "/osc/test"
  puts n
end

live_loop :send_osc do
  osc_send "127.0.0.1", 4559, "/test", 1
  osc_send "127.0.0.1", 4559, "/test", 2
  osc_send "127.0.0.1", 4559, "/test", 3
  sleep 4
end

Observed behavior:


##| /live_loop/send_osc  []
##| /osc/test  [3]
##| /osc/test  [2]
##| /osc/test  [1]
##| /live_loop/read_osc  [] -> 3
##| /live_loop/read_osc  [] -> 2

I'd expect the three value to be received by the read_osc loop (at least if the flag is set to use_real_time)


##| /live_loop/send_osc  []
##| /osc/test  [3]
##| /osc/test  [2]
##| /osc/test  [1]
##| /live_loop/read_osc  [] -> 3
##| /live_loop/read_osc  [] -> 1
##| /live_loop/read_osc  [] -> 2

slvlirnoff avatar Feb 28 '18 02:02 slvlirnoff

Hi there,

I'm unfortunately unable to reproduce your observed behaviour locally. Could you let me know which platform you're on?

Also, could you try running the following code:


live_loop :read_osc do
  use_real_time
  n, _ = sync "/osc/test"
  play 70
  cue :received, n
end

live_loop :send_osc do
  osc_send "127.0.0.1", 4559, "/test", rand
  osc_send "127.0.0.1", 4559, "/test", rand
  osc_send "127.0.0.1", 4559, "/test", rand
  sleep 1
  
  2.times {cue :eggs}
  sleep 3
end

If you could print out your cue log here, that would be very useful indeed :-)

samaaron avatar Mar 05 '18 20:03 samaaron

HI @samaaron

I'm on windows with latest version from Sonic Pi.

I've played with the amount of message sent (3 then 4 then 10) and you can see that the amount of message received vary. In my view it seems to be linked to "time".

 /live_loop/send_osc  []
 /live_loop/read_osc  []
 /osc/test  [0.472076416015625]
 /osc/test  [0.764617919921875]
 /osc/test  [0.957244873046875]
 /cue/received        [0.472076416015625]
 /live_loop/read_osc  []
 /cue/received        [0.764617919921875]
 /live_loop/read_osc  []
 /cue/eggs  []
 /cue/eggs  []
 /live_loop/send_osc  []
 /osc/test  [0.515594482421875]
 /osc/test  [0.272064208984375]
 /osc/test  [0.677398681640625]
 /cue/received        [0.515594482421875]
 /live_loop/read_osc  []
 /cue/received        [0.272064208984375]
 /live_loop/read_osc  []
 /cue/eggs  []
 /cue/eggs  []

=> Redefining fn :live_loop_read_osc

=> Redefining fn :live_loop_send_osc

{run: 10, time: 5.0, thread: :live_loop_read_osc}
 └─ sync "/osc/test"
 
{run: 10, time: 5.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.957244873046875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.764617919921875]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.472076416015625]
 
{run: 10, time: 5.5144, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.472076416015625]
 ├─ cue :received, [0.472076416015625]
 └─ sync "/osc/test"
 
{run: 10, time: 5.515, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.764617919921875]
 ├─ cue :received, [0.764617919921875]
 └─ sync "/osc/test"
 
{run: 10, time: 6.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
{run: 10, time: 9.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.677398681640625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.272064208984375]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.515594482421875]
 
{run: 10, time: 9.5159, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.515594482421875]
 ├─ cue :received, [0.515594482421875]
 └─ sync "/osc/test"
 
{run: 10, time: 9.5164, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.272064208984375]
 ├─ cue :received, [0.272064208984375]
 └─ sync "/osc/test"
 
{run: 10, time: 10.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
=> Stopping all runs...


=> Starting run 4

=> Redefining fn :live_loop_read_osc

=> Redefining fn :live_loop_send_osc

{run: 4, time: 0.0, thread: :live_loop_read_osc}
 └─ sync "/osc/test"
 
{run: 4, time: 0.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.957244873046875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.764617919921875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.472076416015625]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.677398681640625]
 
{run: 4, time: 0.5106, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.677398681640625]
 ├─ cue :received, [0.677398681640625]
 └─ sync "/osc/test"
 
{run: 4, time: 0.511, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.472076416015625]
 ├─ cue :received, [0.472076416015625]
 └─ sync "/osc/test"
 
{run: 4, time: 1.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
{run: 4, time: 4.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.272064208984375]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.515594482421875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.209259033203125]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.859161376953125]
 
{run: 4, time: 4.515, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.859161376953125]
 ├─ cue :received, [0.859161376953125]
 └─ sync "/osc/test"
 
{run: 4, time: 4.516, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.515594482421875]
 ├─ cue :received, [0.515594482421875]
 └─ sync "/osc/test"
 
{run: 4, time: 4.517, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.272064208984375]
 ├─ cue :received, [0.272064208984375]
 └─ sync "/osc/test"
 
{run: 4, time: 5.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
{run: 4, time: 8.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.238189697265625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.03424072265625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.233367919921875]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.057586669921875]
 
{run: 4, time: 8.5102, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.057586669921875]
 ├─ cue :received, [0.057586669921875]
 └─ sync "/osc/test"
 
{run: 4, time: 8.5107, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.233367919921875]
 ├─ cue :received, [0.233367919921875]
 └─ sync "/osc/test"
 
{run: 4, time: 8.5112, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.238189697265625]
 ├─ cue :received, [0.238189697265625]
 └─ sync "/osc/test"
 
{run: 4, time: 9.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
=> Stopping all runs...

=> Stopping run 4

=> Completed run 4

=> All runs completed

=> Pausing SuperCollider Audio Server

=> Starting run 5

=> Redefining fn :live_loop_read_osc

=> Redefining fn :live_loop_send_osc

{run: 5, time: 0.0, thread: :live_loop_read_osc}
 └─ sync "/osc/test"
 
{run: 5, time: 0.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.957244873046875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.764617919921875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.472076416015625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.677398681640625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.272064208984375]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.515594482421875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.209259033203125]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.859161376953125]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.238189697265625]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.03424072265625]
 
{run: 5, time: 0.5149, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.03424072265625]
 ├─ cue :received, [0.03424072265625]
 └─ sync "/osc/test"
 
{run: 5, time: 0.5159, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.515594482421875]
 ├─ cue :received, [0.515594482421875]
 └─ sync "/osc/test"
 
{run: 5, time: 1.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
{run: 5, time: 4.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.233367919921875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.057586669921875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.03759765625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.959930419921875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.2010498046875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.38134765625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.599822998046875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.038726806640625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.77362060546875]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.8564453125]
 
{run: 5, time: 4.5096, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.8564453125]
 ├─ cue :received, [0.8564453125]
 └─ sync "/osc/test"
 
{run: 5, time: 4.5106, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.2010498046875]
 ├─ cue :received, [0.2010498046875]
 └─ sync "/osc/test"
 
{run: 5, time: 4.5116, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.03759765625]
 ├─ cue :received, [0.03759765625]
 └─ sync "/osc/test"
 
{run: 5, time: 4.5126, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.233367919921875]
 ├─ cue :received, [0.233367919921875]
 └─ sync "/osc/test"
 
{run: 5, time: 5.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
{run: 5, time: 8.0, thread: :live_loop_send_osc}
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.9029541015625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.0848388671875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.748870849609375]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.8543701171875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.471099853515625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.04547119140625]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.686798095703125]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.042694091796875]
 ├─ OSC -> 127.0.0.1, 4559, /test, [0.110748291015625]
 └─ OSC -> 127.0.0.1, 4559, /test, [0.147125244140625]
 
{run: 5, time: 8.5112, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.147125244140625]
 ├─ cue :received, [0.147125244140625]
 └─ sync "/osc/test"
 
{run: 5, time: 8.5117, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.042694091796875]
 ├─ cue :received, [0.042694091796875]
 └─ sync "/osc/test"
 
{run: 5, time: 8.5122, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.471099853515625]
 ├─ cue :received, [0.471099853515625]
 └─ sync "/osc/test"
 
{run: 5, time: 8.5132, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.0848388671875]
 ├─ cue :received, [0.0848388671875]
 └─ sync "/osc/test"
 
{run: 5, time: 8.5137, thread: :live_loop_read_osc}
 ├─ synced "/osc/test" 
 ├─ synth :beep, {note: 70.0}
 ├─ set :received, [0.9029541015625]
 ├─ cue :received, [0.9029541015625]
 └─ sync "/osc/test"
 
{run: 5, time: 9.0, thread: :live_loop_send_osc}
 ├─ set :eggs, []
 ├─ cue :eggs, []
 ├─ set :eggs, []
 └─ cue :eggs, []
 
=> Stopping all runs...

=> Stopping run 5

=> Completed run 5

=> All runs completed

=> Pausing SuperCollider Audio Server

slvlirnoff avatar Mar 08 '18 20:03 slvlirnoff

Hi @samaaron

I've put some debug here and there in event_history.rb to dump the state of the events and compared it with the received cue value.

Here's the finding so far:

 /osc/test  [0.03424072265625]
 /osc/test  [0.238189697265625]
 /osc/test  [0.859161376953125]
 /osc/test  [0.209259033203125]
 /osc/test  [0.272064208984375]
 /osc/test  [0.677398681640625]
 /osc/test  [0.472076416015625]
 /osc/test  [0.764617919921875]
 /osc/test  [0.957244873046875]
 /osc/test  [0.515594482421875]

      events.each {
        |se|
         puts "event in history #{se.time.strftime("%M:%S:%L:%N")}, #{se.priority}, #{se.thread_id}, #{se.delta}, #{se.beat}, #{se.bpm} #{se.val}" 
      }

->
OK event in history 36:35:131:131687000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.515594482421875]
 
KO event in history 36:35:131:131186000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.957244873046875]
OK event in history 36:35:131:131186000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.764617919921875] 

KO event in history 36:35:130:130683000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.472076416015625]
KO event in history 36:35:130:130683000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.677398681640625]
OK event in history 36:35:130:130683000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.272064208984375] 

OK event in history 36:35:129:129682000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.209259033203125] 

KO event in history 36:35:129:129182000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.859161376953125]
OK event in history 36:35:129:129182000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.238189697265625]

OK event in history 36:35:128:128682000, 0, #<SonicPi::ThreadId [-1]>, 0, 0.0, 60.0 [0.03424072265625]

 /cue/received  [0.03424072265625]
 /live_loop/read_osc  []
 /cue/received  [0.238189697265625]
 /live_loop/read_osc  []
 /cue/received  [0.209259033203125]
 /live_loop/read_osc  []
 /cue/received  [0.272064208984375]
 /live_loop/read_osc  []
 /cue/received        [0.764617919921875]
 /live_loop/read_osc  []
 /cue/received        [0.515594482421875]
 /live_loop/read_osc  [] 

As you can see, some event have exactly the same 'time' value and for these one, only the latest is returned. I guess this is the culprit.

slvlirnoff avatar Mar 08 '18 21:03 slvlirnoff

Excellent sleuthing - thanks so much. This is definitely enough to go on.

Interestingly, I was able to reproduce this behaviour on my Windows VM, but on my Mac, all the messages always were received.

samaaron avatar Mar 08 '18 21:03 samaaron

Thank you @samaaron I guess time precision is "lower" on ruby windows.

I might have some time to try to propose a fix for this issue this weekend. Do you have some guidance on how you would like the solution to be approached?

I'd see it either at event creation/state insertion, making sure time key is unique or at get_next making sure to iterate over events with identical times.

slvlirnoff avatar Mar 14 '18 10:03 slvlirnoff

Hello @slvlirnoff - it's possible this issue is related to the accuracy of timing in Erlang on Windows. If so, it's possible this issue is solved with updates to Erlang's timing resolution on Windows, included in the upcoming release of Sonic Pi v4.0. If you are a Patreon, you'll be able to test this out with our Betas available there - otherwise this may be solved when the official v4.0 release is out in the (hopefully) not too distant future.

ethancrawford avatar Oct 12 '21 08:10 ethancrawford

@ethancrawford hey, do you know if this has been fixed in the latest 4.x release? I will try at some point and see if I can reproduce the issue.

slvlirnoff avatar Sep 04 '22 09:09 slvlirnoff