Low latency Android & Arduino bluetooth -


i'm sampling audio on android, , sending rgb values based on arduino device using bluetooth.

there's long delay (several seconds) between audio samples being sent, , arduino reacting. i'm assuming caused android being faster arduino, , sort of flow control going on transmitting bytes getting backed buffer on phone. code connect bluetooth is:

mmsocket = mmdevice.createrfcommsockettoservicerecord(uuid); mmsocket.connect(); mmoutputstream = mmsocket.getoutputstream(); 

and send data:

mmoutputstream.write(0xff); mmoutputstream.write(outputfreq); mmoutputstream.write(outputmagnitude); 

i don't mind losing data, need recent values sent.

what best way achive this? i'm new android programming work quite simpler solutions better! i've though sort of stack, , seperate thread runs on timer, , skims top of stack , sends values, sounds quite complex don't know thread programming.

is there way instead configure outputstream discards data hasn't been sent in time?

here full code if it's help:

package com.example.fft1;  import java.io.ioexception; import java.io.inputstream; import java.io.outputstream; import java.util.arrays; import java.util.list; import java.util.set; import java.util.uuid;  import com.androidplot.series.xyseries; import com.androidplot.xy.boundarymode; import com.androidplot.xy.lineandpointformatter; import com.androidplot.xy.xyplot; import com.androidplot.xy.simplexyseries;   import edu.emory.mathcs.jtransforms.fft.doublefft_1d; import android.graphics.color; import android.media.audioformat; import android.media.audiorecord; import android.media.mediarecorder; import android.os.asynctask; import android.os.bundle; import android.app.activity; import android.bluetooth.bluetoothadapter; import android.bluetooth.bluetoothdevice; import android.bluetooth.bluetoothsocket; import android.content.intent; import android.util.log; import android.view.menu; import android.view.view; import android.widget.button; import android.widget.textview;  public class mainactivity extends activity  {      xyplot plot;     simplexyseries plotseries;     audiorecord audiorecord;     recordaudio recordtask;     int frequency = 44100;     int channelconfiguration = audioformat.channel_in_mono;     int audioencoding = audioformat.encoding_pcm_16bit;       bluetoothadapter mbluetoothadapter;     bluetoothsocket mmsocket;     bluetoothdevice mmdevice;     outputstream mmoutputstream;     inputstream mminputstream;      int counter;       @suppresswarnings("deprecation")     @override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);         setcontentview(r.layout.activity_main);          // initialize our xyplot reference:         plot = (xyplot) findviewbyid(r.id.mysimplexyplot);         plot.setrangeboundaries(-1000000, 1000000, boundarymode.fixed);         number[] seriesdata = {1,2,3,4,5,6};         // turn above arrays xyseries':         plotseries = new simplexyseries(                 arrays.aslist(seriesdata),          // simplexyseries takes list turn our array list                 simplexyseries.arrayformat.y_vals_only, // y_vals_only means use element index x value                 "series1");                             // set display title of series           // create formatter use drawing series using lineandpointrenderer:         @suppresswarnings("deprecation")         lineandpointformatter series1format = new lineandpointformatter(                 color.rgb(0, 200, 0),                   // line color                 color.rgb(0, 100, 0),                   // point color                 null);                                  // fill color (none)          // add new series' xyplot:         plot.addseries(plotseries, series1format);          // reduce number of range labels         plot.setticksperrangelabel(3);          // default, androidplot displays developer guides aid in laying out plot.         // rid of them call disableallmarkup():         plot.disableallmarkup();          button startbtn = (button)findviewbyid(r.id.startbutton);          int buffersize = audiorecord.getminbuffersize(frequency, channelconfiguration, audioencoding);         audiorecord = new audiorecord(                 mediarecorder.audiosource.default,                  frequency,                 channelconfiguration,                  audioencoding,                  buffersize                 );           startbtn.setonclicklistener(new startbtnclick());          button connectbtn = (button)findviewbyid(r.id.connectbtn);         connectbtn.setonclicklistener(new connectbtnclick());       }      class startbtnclick implements button.onclicklistener {         @override         public void onclick(view view) {             button button = (button) view;             if (button.gettext().tostring().equals("start")) {                 button.settext("stop");                 recordtask  = new recordaudio();                 recordtask.execute();             } else {                 button.settext("start");                 recordtask.cancel(false);             }         }      }       class connectbtnclick implements button.onclicklistener {         @override         public void onclick(view view) {              mbluetoothadapter = bluetoothadapter.getdefaultadapter();              if(!mbluetoothadapter.isenabled()) {                 intent enablebluetooth = new intent(bluetoothadapter.action_request_enable);                 startactivityforresult(enablebluetooth, 0);             }              set<bluetoothdevice> paireddevices = mbluetoothadapter.getbondeddevices();             if(paireddevices.size() > 0) {                 for(bluetoothdevice device : paireddevices) {                     log.v("bt2", "device: " + device.getname());                     if(device.getname().equals("linvor")) {                         mmdevice = device;                         break;                     }                 }             }              uuid uuid = uuid.fromstring("00001101-0000-1000-8000-00805f9b34fb"); //standard serialportservice id             try {                 mmsocket = mmdevice.createrfcommsockettoservicerecord(uuid);                  mmsocket.connect();                 mmoutputstream = mmsocket.getoutputstream();                 mminputstream = mmsocket.getinputstream();                  (int = 0; < 255; i++) {                     mmoutputstream.write(0xff);                     mmoutputstream.write(i);                     mmoutputstream.write(255);                 }             } catch (ioexception e) {                 // todo auto-generated catch block                 e.printstacktrace();             }           }         //beginlistenfordata();     }       private class recordaudio extends asynctask<void, integer[], void> {         @override         protected void doinbackground(void... params) {               int blocksize = 128;             short[] buffer = new short[blocksize];             double[] bufferd = new double[blocksize];             audiorecord.startrecording();              // here's fast fourier transform jtransforms             doublefft_1d fft = new doublefft_1d(buffer.length);               while (!iscancelled()) {                 counter = (counter + 1) % 1000;                 //log.v("fft1", string.valueof(counter));                 int sumenergy = 0;                 logtime("start");                 // read audio 'samples' array , convert double[]                 audiorecord.read(buffer, 0, buffer.length);                 logtime("after reading");                  (int = 0; < buffer.length; i++) {                     bufferd[i]=buffer[i];                 }                  fft.realforward(bufferd);                 logtime("after fft");                 integer[] spectrum = new integer[blocksize/2];                 (int k = 0; k < blocksize / 2; k++) {                     spectrum[k] = new integer((int) math.sqrt( (bufferd[2*k] * bufferd[2*k]) + (bufferd[2*k+1] * bufferd[2*k+1]) ));                    }                  int averagemagnitude = 0;                 int middlefreqbin = 0;                 (int = 0; < spectrum.length; i++) {                     averagemagnitude += spectrum[i];                 }                 averagemagnitude /= spectrum.length;                  int halfmagnitudesum = 0;                 (int = 0; < spectrum.length / 2; i++) {                     halfmagnitudesum += spectrum[i] * i;                 }                 halfmagnitudesum /= 2;                 int runningtotal = 0;                 (int = 0; < spectrum.length; i++) {                     runningtotal += spectrum[i] * i;                     if (runningtotal > halfmagnitudesum) {                         middlefreqbin = i;                         break;                     }                 }                  int outputmagnitude = map(averagemagnitude, 0, 50000, 0, 254);                 int outputfreq = map(middlefreqbin, 0, spectrum.length, 0, 254);                 if (outputmagnitude > 254) outputmagnitude = 254;                  try {                     //log.v("fft1", "outputfreq: " + outputfreq + ", outputmagnitude: " + outputmagnitude);                     mmoutputstream.write(0xff);                     mmoutputstream.write(outputfreq);                     mmoutputstream.write(outputmagnitude);                     thread.sleep(10);                  } catch (exception e) {                     // todo auto-generated catch block                     log.v("fft1","not connected");                 }                                 logtime("after bluetooth");                  publishprogress(spectrum);              }             return null;            }          protected void oncancelled() {             audiorecord.stop();         }          protected void onprogressupdate(integer[]... args) {             integer[] spectrum = args[0];              plotseries.setmodel(arrays.aslist(spectrum),  simplexyseries.arrayformat.y_vals_only);             plot.redraw();         }          int map(int x, int in_min, int in_max, int out_min, int out_max)    {             return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;         }      }      @override     public boolean oncreateoptionsmenu(menu menu) {         // inflate menu; adds items action bar if present.         getmenuinflater().inflate(r.menu.main, menu);         return true;     }      public void logtime(string text) {          if (counter < 5) {             string time =  string.valueof(new java.util.date().gettime());             log.v("fft1", text + ": " + time.substring(time.length()-4, time.length()));         }     }  } 

the outputstream.write(); lines returned immediately, amount of delay increased on time. data getting backed somewhere in bluetooth stack, why put in thread.sleep(10), try , slow things down.

that caused other problems around blocking though, , replaced couple of lines check when last write() before sending new data. if less configured time (call timedelay), skips new write(). manually tuning value of timedelay enabled me avoid flooding bluetooth stack. in


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

c++ - End of file on pipe magic during open -