【问题标题】:Get Android AudioRecord startRecording time delay获取 Android AudioRecord startRecording 时间延迟
【发布时间】:2013-05-07 17:43:14
【问题描述】:

我正在使用来自https://github.com/nonameentername/soundtouch-android/blob/master/src/org/tecunhuman/ExtAudioRecorder.javaAudioRecord 类,但稍作修改。

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

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

为了更好的解释:

开始录音

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

Beat/Instrumental 之后开始播放

[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);
    }
};

【问题讨论】:

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

标签: android android-mediaplayer android-audiorecord


【解决方案1】:

我不明白“时间总是关闭”?什么意思?

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

如果是这种情况,您必须考虑您的 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() 不会为您的代码块创建单独的线程,而只会将带有计时器标签的新消息(与您的 Runnable 实例相关)附加到当前线程的消息队列中。

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

修改问题更新:

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

  • 在您使用处理程序的同一线程中,您几乎不会同步 2 个函数(正如我提到的,handler.run() 不会产生分离的线程)。

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

我建议的解决方案:

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

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

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

【讨论】:

  • 编辑了问题。我需要人声和乐器以与他们录制相同的方式在设备上播放。目前播放不同步。与乐器相比,人声要么延迟要么太快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-19
  • 2011-12-29
  • 1970-01-01
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多