sojamo / oscp5

An Open Sound Control (OSC) implementation for Java and Processing
GNU Lesser General Public License v2.1
132 stars 51 forks source link

Problem capturing a large number of quick successive messages in oscEvent method on Android #10

Open faxinadu opened 6 years ago

faxinadu commented 6 years ago

When I try to send many OSC messages at once, it seems the oscEvent method only listens to some of the messages (around anywhere between 20 and 50 out of around 200) so and disregards the rest.

Below there is quick code to test this on Android. When run on a device this will print to the run console all incoming OSC messages. here it is showing only 27 messages captured by the oscEvent method:

27

I am sending 200 messages each with a unique address (loading a preset on a computer, this preset should update all the parameters on the Android device).

Steps to recreate: 1 - Run below code on Android device 2 - Update preset on OSC capable music synthesizer vsti plugin on the computer Expected result: all addresses and messages caught by oscEvent method and logged in run console. Actual result: only a fraction of the messages are caught.

Using network sniffing with Wireshark, I can confirm that the source is sending all these messages and Wireshark is picking them up in an orderly fashion:

shark

Quick testing code:

import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import netP5.NetAddress;
import oscP5.OscMessage;
import oscP5.OscP5;

public class MainActivity extends AppCompatActivity {

    int evenCount = 0;
    OscP5 oscP5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        oscLink();
    }

    void oscLink(){
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        oscP5 = new OscP5(this,9000);
    }

    public void oscEvent(OscMessage theOscMessage) {

        evenCount = evenCount + 1;

        System.out.println(" addrpattern: " + theOscMessage.addrPattern());
        System.out.println(" typetag: " + theOscMessage.typetag());
        System.out.println(" msg: " + theOscMessage.get(0).intValue());

        System.out.println(evenCount);
    }
}
faxinadu commented 6 years ago

just to add that same test with async task instead of strict mode yields same results.

sojamo commented 6 years ago

Hi, all the messages are sent:

1) but do they arrive on your android device? They might have been dropped on the way (UDP is an unreliable protocol and packet losses are expected to happen).

2) can you bundle the messages and send them as an OSC-Bundle (you might have to increase the datagram-size, see oscP5properties example )?

2) try to run the following (this will run a UDP server and pass the bytes received directly to the Observer, extract the relevant parts and insert into your android code) code below is a Processing sketch

import netP5.*;
import oscP5.*;
import java.util.*;

UdpServer server;

void setup() {
  server = NetP5.createUdpServer(8000, 1024);

  server.addObserver(new Observer() {
    int n = 0;
    public void update(Observable obs, Object obj) {
      println("received packet ", n++);
      parse(obj);
    }
  }
  );
}

void draw() {}

void keyPressed() {
  for (int i=0; i<200; i++) { 
    server.send(new OscMessage("/test", i).getBytes(), "127.0.0.1", 8000);
  }
}

void parse(Object o) {
  OscMessage message = new OscMessage("");
  byte[] bytes = (byte[])((Map)o).get("data");
  message.parseMessage(bytes);
  println(message);
}
faxinadu commented 6 years ago

thanks for the reply, really appreciated as aside from this issue everything else is working beautifully including bi-directional data binding between a complex pc app and android app.

i have elaborated here on my testing example code/app and will now incorporate your udp server into the test as well and report back.

can you bundle the messages and send them as an OSC-Bundle (you might have to increase the datagram-size, see oscP5properties example )?

this might work i am not sure, but it is also i think somewhat un-satisfactory in this situation. when you move a single knob on the pc synth, this knob sends out a single osc message. preset changing is based on the knobs as well, so when a preset is loaded on the pc each knob gets updated and this triggers the sending of the osc message. so it seems convoluted to set up a whole system of logic for the knobs where only if the update comes from a preset pack a bundle instead of a message.

faxinadu commented 6 years ago

image

getting a few reds here trying to adapt the code to android studio: createUdpServer can not resolve method addObserver can not resolve method

parseMessage has protected access

faxinadu commented 6 years ago

but do they arrive on your android device? They might have been dropped on the way (UDP is an unreliable protocol and packet losses are expected to happen).

I understand packet loses will happen, but this is something more consistent here - EVERY time when sending 200 in quick succession around 150/200 are dropped. Also it seems that the ones that do arrive are the ones that are sent first - the first 50 or so parameters loaded in the synth by it's preset file.

faxinadu commented 6 years ago

I ended up solving it from another direction - slowing down the rate at which a preset from the synth sends to the app. not ideal since now a preset takes a few seconds to sync between device<->app, but at least it works now.