获取Android录音开始录制时间延迟

获取Android录音开始录制时间延迟,android,android-mediaplayer,android-audiorecord,Android,Android Mediaplayer,Android Audiorecord,我使用的是来自的AudioRecord类,但对其进行了轻微修改 在start()方法中,我使用AudioRecord类开始录制。我还启动了一个MediaPlayer来演奏器乐。为了让人声和乐器在服务器上的正确位置混合,我发送乐器延迟,以在乐器开始时用静音填充乐器(beatDelayInSeconds-MediaPlayer从调用start开始到实际播放的延迟,因为启动media player时存在延迟) 我的逻辑一定是错误的,因为设备上的人声和乐器的播放时间是关闭的。有时录音会太快,有时与乐器演

我使用的是来自的
AudioRecord
类,但对其进行了轻微修改

start()
方法中,我使用
AudioRecord
类开始录制。我还启动了一个
MediaPlayer
来演奏器乐。为了让人声和乐器在服务器上的正确位置混合,我发送乐器延迟,以在乐器开始时用静音填充乐器(beatDelayInSeconds-
MediaPlayer
从调用start开始到实际播放的延迟,因为启动media player时存在延迟)

我的逻辑一定是错误的,因为设备上的人声和乐器的播放时间是关闭的。有时录音会太快,有时与乐器演奏时相比会太慢。任何建议。任何帮助都将不胜感激

为了更好地解释:

开始录音

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

节拍/器乐之后开始演奏

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

我正在尝试查找X,以便可以将其作为beatDelayInSeconds发送到startPlayback()方法并发送到服务器。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);
    }
};
我不明白“时间总是不定”?这是什么意思

我不太清楚您的问题和描述,但这是真的吗:您想在一段时间后推迟代码块的执行

如果是这种情况,则必须考虑是否在另一个UI线程中调用了<强> >代码>新的HANDLE()。如果是活动的流程,请尝试以下操作:

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

               //your work load here
            }
});
注:

  • postDelayed()不会为代码块创建单独的线程,而只是将一条新消息(与可运行实例相关)和计时器标签附加到当前线程的消息队列中

  • activity.runOnUiThread()执行类似的操作,但是
    Runnable.run()
    必须等待系统返回到活动UI线程,然后才能执行。当您想在其子线程中执行某些活动的工作时,这会很有帮助

修改问题的更新:

我可能理解您的意图:尝试同时执行
wavPlayer.start()
mp3Player.start()
;但您当前的解决方案不好,甚至不可能:

  • 在使用处理程序的同一个线程中,很难同步这两个函数(正如我提到的,handler.run()不会产生分离的线程)

  • 您无法确定hanler.run()的确切时间戳,因为系统控制消息何时附加到队列中,post DELATED是一个相对值

我建议的解决办法是:

  • 您为每个玩家生成一个单独的线程

  • 在每个线程开始()之前,标记时间戳(可以使用毫秒,而不是使用nano的精度)

  • 在后面调用的第二个线程中,还将时间戳的增量(标记之间的差异)传递给它。然后使用
    Thread.Sleep()
    Handler.postDelayed()
    调整同步


@nawlrus。。在您的问题中,您引用了“在服务器上同步这些”。我知道您正在尝试录制并同时播放内容。我无法理解复制的评论的上下文。你能澄清一下吗?对不起,甘尼什。我已经编辑并添加了更多信息。我发送beatDelayInseconds和RecordDelayInSeconds,其等于RecordReadDelayInSeconds+RecordDelayInSeconds。服务器负责从那里处理媒体,但我认为在录制之后,处理和播放的延迟时间不正确。@nawlrus。。因此,如果我理解正确,您正在尝试记录一些数据,将其传输到服务器,从服务器接收相同的数据,并在同一设备上播放。这种理解正确吗?如果这是真的,如果在播放过程中录制会话处于打开状态,您不会遇到环路内回音或背景回音吗?这可以接受吗?还有一点。即使录像机有启动延迟,一旦它开始流出数据,它也必须遵守一些比特率规定,因此即使你的mediaplayer启动晚了,理想情况下也不应该有下溢。这不是事实吗?@Ganesh。我让用户录制他们的人声,然后在那时他们可以在设备上播放(无需发送到服务器,只需播放人声并回击;请参阅startPlayback方法)这就是我听到计时关闭的地方。如果用户喜欢录制,我会将BeatDelayUnseconds发送到服务器,服务器会将人声和乐器混合在一起。我需要人声和乐器在设备上以他们录制的方式播放。当前播放不同步。与器乐相比,人声可能会延迟或过快。