2015-09-08 2 views
0

Я разрабатываю программное обеспечение для обработки аудио в реальном времени, которое должно обновлять пользовательский интерфейс не менее чем за 100 мс от рабочего потока. Однако это кажется труднее достичь, чем кажется.Обновление UI немедленно для обработки в реальном времени

Я звоню runOnUiThread(uiUpdaterRunnable) из рабочего потока, но задержка выполнения uiUpdaterRunnable является переменной и обычно более 300 мс.

Я попытался использовать AsyncTask с publishProgress, но также дал мне похожие результаты.

Как я могу обновить пользовательский интерфейс из рабочего потока, чтобы получить как минимум 10FPS?

Вот работоспособный мой рабочий поток:

new Runnable() { 
public void run() { 
try { 



      int sampleRate = 44100; 
      int audioFormat = AudioFormat.ENCODING_PCM_16BIT; 
      int channelConfig = MediaRecorder.AudioSource.MIC; 
      int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); 
      audioRecorder = new AudioRecord(channelConfig, sampleRate, AudioFormat.CHANNEL_IN_MONO, audioFormat, bufferSize); 
      if (bufferSize == AudioRecord.ERROR_BAD_VALUE) 
       Log.i("AudioRecord", "AudioRecord Bad Buffer Size"); 
      if (audioRecorder.getState() == AudioRecord.STATE_INITIALIZED) 
       Log.i("AudioRecord", "AudioRecord Initialized Successfully"); 

      audioRecorder.startRecording(); 
     while (recording) { 
      startTime = System.currentTimeMillis(); 
      short[] buffer = new short[bufferSize]; 
      audioRecorder.read(buffer, 0, bufferSize); 

      double[] bufferDouble = shortToDoubleArray(buffer); 

      final DataPoint[] resultArray = getFFTResult(bufferDouble); 


      //This is where I update UI 
      runOnUiThread(new Runnable() { 
       public void run() { 
       updateGraph(resultArray); 
       } 
      }); 

     } 
     releaseAudioResources(); 
    } catch (Exception e) { 
     if (e.getMessage() == null) 
      e.printStackTrace(); 
     else 
      Log.e("Exception", e.getMessage()); 
     releaseAudioResources(); 
    } 
} 
+0

вы пытались Handler, чтобы отправить сообщение, когда ваша работа сделана и обновление пользовательского интерфейса? –

+0

Да, я попробовал. Это почти эквивалентно 'runOnUiThread', выполнение обработчика слишком задерживается. –

+0

Для более быстрого обновления вам может потребоваться «SurfaceView» или даже «GLSurfaceView». Это будет значительным изменением, однако, вашей рабочей структуры. – Tigger

ответ

1
} 
.... 
// write this outside your code block 
Handler mHandler = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
     super.handleMessage(msg); 
     updateGraph(resultArray); 
    } 
}; 
// to call it inside runnable 
mHandler.sendEmptyMessage(0); 
+0

Обновление: Я узнал, что падение задержки связано с повторным обновлением startTime до того, как сообщение будет обработано. Когда я исправил код, чтобы дождаться, пока сообщение будет обработано (например, обновление пользовательского интерфейса), задержка снова превысит 300 мс. Итак, проблема не решена :( –

+0

Хорошо, я посмотрю. Тогда вы можете проверить это https://developer.android.com/training/multiple-threads/communicate-ui.html –

+0

и что вы можете сделать Предварительный просмотр пользовательского интерфейса пользователю и публикация обновления данных в том, что после того, как вы завершили процесс. Это улучшит визуальный опыт для пользователя –