2013-04-03 50 views
0

我使用的是https://github.com/nonameentername/soundtouch-android/blob/master/src/org/tecunhuman/ExtAudioRecorder.java中的AudioRecord類,但稍作修改。獲取Android AudioRecord開始錄製時間延遲

start()方法中,我開始用AudioRecord類記錄。我也開始MediaPlayer發揮工具。爲了讓人聲和樂器在服務器上的正確位置混合,我發送了樂器延遲,以開始時用沉默(padDelayInSeconds - MediaPlayer延遲從開始被調用到實際播放時的延遲,因爲存在延遲當啓動媒體播放器時)。

我的邏輯必須是錯誤的,因爲人聲和樂器的播放時序在設備上是關閉的。有些時候錄音速度太快,有時會比樂器演奏時慢。有什麼建議麼。任何幫助將不勝感激。

爲了更好的解釋:

錄音開始

| ------------------------------ ---------- |

節拍/器樂開始播放後

[X] | -------------------------------- --------------- |

我想找到X,所以我可以發送到startPlayback()方法beatDelayInSeconds和服務器。 X是聲音開始錄製到節拍實際開始播放之間的時間。目前在我的startPlayback()方法中,同時播放節拍和人聲,它們不像錄製的那樣同步。希望這是有道理的。

注意:我不得不在延遲處理程序中放置一些Jelly Bean設備,因爲AudioRecord偵聽程序沒有被調用。

public void start() 
{ 
    if (state == State.READY) 
    { 
     if (rUncompressed) 
     { 
      payloadSize = 0; 
      RecordReadDelayInSeconds = 0; 
      RecordDelayInSeconds = 0; 

      mPlayer = new MediaPlayer(); 

      try { 

       mPlayer.setDataSource(mp3Path); 

       mPlayer.prepare(); 

      } catch (IllegalArgumentException e) {e.printStackTrace();} 
       catch (SecurityException e) {e.printStackTrace();} 
       catch (IllegalStateException e) {e.printStackTrace();} 
       catch (IOException e) { e.printStackTrace();} 

      final long recordstarted = System.nanoTime() + 1500000000; //handler delay 

      audioRecorder.startRecording(); 

      //Fix for recording issue with Samsung s3 Sprint phones.Doing a delayed first read 
       new Handler().postDelayed(new Runnable() {      
        @Override 
        public void run() { 

         long recordstopped = System.nanoTime(); 

         long recordDelay = recordstopped - recordstarted; 

         double RecordDelayInSeconds = recordDelay/1000000.0; 

         Log.i("StartRecording() Delay in seconds", 
           String.valueOf(RecordDelayInSeconds)); 

         long recordreadstarted = System.nanoTime(); 

         int bytesReceived = audioRecorder.read(buffer, 0, buffer.length); 
         Log.d(TAG,"Delayed first read: bytes recieved "+ bytesReceived); 

         long recordreadstopped = System.nanoTime(); 

         long recordreadDelay = recordreadstopped - recordreadstarted; 

         RecordReadDelayInSeconds = recordreadDelay/1000000.0; 

         Log.i("Record read() Delay in seconds", 
           String.valueOf(RecordReadDelayInSeconds)); 

         long mediastarted = System.nanoTime(); 

         mPlayer.start(); 

         long mediastopped = System.nanoTime(); 

         long beatDelay = mediastopped - mediastarted; 

         beatDelayInSeconds = 0; 

         beatDelayInSeconds = (beatDelay)/1000000000.0; 

         Log.i("Beat Delay in seconds", 
           String.valueOf(beatDelayInSeconds)); 

        } 
       }, 1500); 
} 

這是用戶在向服務器發送信息之前偵聽的回放代碼。它首先開始播放用戶剛錄製的wav,然後根據另一種方法的beatDelayInSeconds變量播放樂器。

private void startPlayback() { 

    wavPlayer.start(); 
    RefreshHandler mp3PlaybackHandler = new RefreshHandler(); 
      mp3PlaybackHandler.sleep((long) (beatDelayInSeconds * 1000)); 

} 

class RefreshHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
     mp3Player.start(); 
    } 

    public void sleep(long delayMillis) { 
     this.removeMessages(0); 
     Log.i(TAG, "Beat delayed for " + delayMillis + " milliseconds"); 
     sendMessageDelayed(obtainMessage(0), delayMillis); 
    } 
}; 
+0

@nawlrus ..在你的問題中,你引用了「讓它們在服務器上同步」。我知道您正在嘗試錄製並同時播放內容。我無法理解轉載的評論的背景。你能澄清一下嗎? – Ganesh

+0

對不起Ganesh。我編輯並添加了更多信息。我發送beatDelayInseconds和一個recordDelay,它等於RecordReadDelayInSeconds + RecordDelayInSeconds。服務器負責從那裏進行媒體處理,但我不認爲我得到了正確的延遲處理和錄製後的回放。 – nawlrus

+0

@nawlrus ..所以,如果我理解正確,你正試圖記錄一些數據,將其流式傳輸到服務器,從服務器接收相同的數據並在同一設備上播放。這種理解是否正確?如果這是真的,如果在回放過程中記錄會話是開啓的,你會不會遇到迴路內回聲或背景回聲?這可以接受嗎?還有一點。即使錄像機存在啓動延遲,一旦它開始流出數據,它必須遵守一些比特率規定,所以即使您的媒體播放器啓動較晚,它也不應該有理想的下溢。不是這樣嗎? – Ganesh

回答

0

我不明白 「時機始終關閉」?這是什麼意思?

我不是很清楚你的問題和你的描述,但它是真的嗎?你想在一段時間後推遲代碼塊的執行嗎?

如果是這樣的話,您必須考慮您的new Handler().postDelayed(..)是否在另一個UI線程內被調用。試試這個,如果它是一個活動的過程:

your_activity_instance.runOnUiThread(new Runnable() 
{ 
      @Override 
      public void run() 
      { 
       //delay with thread 
       try{ 
        Thread.sleep(1500); 
       }catch(.....) 
       {..} 

       //your work load here 
      } 
}); 

注:

  • Handler.postDelayed()不會爲你的代碼塊一個獨立的線程,但只追加新的消息(與您可運行的實例)與計時器貼紙到當前線程的消息隊列中。

  • activity.runOnUiThread()做類似的事情,但Runnable.run()必須等待,直到迴歸到活動UI線程隨後excuted。當你想在其子線程中執行一些活動的工作時,這很有用。

更新修改的問題:

我可以理解你的意圖:試圖執行wavPlayer.start()mp3Player.start()在同一時間;但你目前的解決方案是不是很好,甚至是不可能的:

  • 在同一個線程,你正在使用的處理程序,你幾乎同步的2個功能(如我提到,handler.run()不產生分離的線程)。

  • 當消息被附加到隊列不能牽制的hanler.run()因爲系統控制的精確時間戳,延遲後是一個相對值。

我的建議解決方案:

  • 您產卵每個玩家一個獨立的線程。

  • 之前,每個線程的start(),您標記時間戳(可以使用的毫秒不是這樣的精度,使用納米)

  • 在這後來被稱爲第二個線程,你傳遞給它的時間戳的DELTA(標記之間的差異)。然後使用Thread.Sleep()Handler.postDelayed()用於調整同步。

+0

編輯該問題。我需要人聲和樂器以與他們錄製相同的方式在設備上播放。目前播放不同步。與樂器相比,人聲可能會延遲或太快。 – nawlrus