AudioRecord和AudioTrack延迟

时间:2011-03-21 14:29:53

标签: android audio record audiorecord android-audiorecord

我正在尝试开发像iRig for android这样的应用程序,所以第一步是捕获麦克风输入并同时播放它。

我有它,但问题是我得到一些延迟使得这个无法使用,如果我开始处理缓冲区,我担心它会完全无法使用。

我像这样使用audiorecord和audiotrack:

    new Thread(new Runnable() {
        public void run() {
            while(mRunning){
                mRecorder.read(mBuffer, 0, mBufferSize);
                //Todo: Apply filters here into the buffer and then play it modified
                mPlayer.write(mBuffer, 0, mBufferSize);         
                //Log.v("MY AMP","ARA");
            }

以这种方式表达:

// ==================== INITIALIZE ========================= //
public void initialize(){

    mBufferSize = AudioRecord.getMinBufferSize(mHz, 
                AudioFormat.CHANNEL_CONFIGURATION_MONO, 
                AudioFormat.ENCODING_PCM_16BIT);

    mBufferSize2 = AudioTrack.getMinBufferSize(mHz, 
                AudioFormat.CHANNEL_CONFIGURATION_MONO, 
                AudioFormat.ENCODING_PCM_16BIT);

    mBuffer = new byte[mBufferSize];

    Log.v("MY AMP","Buffer size:" + mBufferSize);

    mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                mHz,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, 
                mBufferSize);

    mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
                mHz,
                AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                mBufferSize2, 
                AudioTrack.MODE_STREAM);    

}

你知道如何获得更快的回复吗? 谢谢!

4 个答案:

答案 0 :(得分:8)

由于最小缓冲区大小,Android的AudioTrack \ AudioRecord类具有高延迟。 这些缓冲区大小的原因是为了最大限度地减少GC发生GC时的丢失(在我看来,这是一个错误的决定,你可以优化自己的内存管理)。

您要做的是使用OpenSL,它可以从2.3获得。它包含用于流式音频的本机API。 这是一些文档: http://mobilepearls.com/labs/native-android-api/opensles/index.html

答案 1 :(得分:1)

只是一个想法,但你不应该阅读< mBufferSize

答案 2 :(得分:0)

我的第一个建议是建议将AudioTrack导入静态模式而不是流模式,因为静态模式的延迟明显较小。但是,静态模式更适合完全适合内存的短音,而不是您从其他地方捕获的声音。但是,如同一个疯狂的猜测,如果您将AudioTrack设置为静态模式并为其提供输入音频的离散块,该怎么办?

如果您想要更严格地控​​制音频,我建议您查看适用于Android的 OpenSL ES 。学习曲线会更加陡峭,但您可以获得更精细的控制和更低的延迟。

答案 3 :(得分:0)

正如mSparks指出的那样,应该使用较小的读取大小进行流式传输:您不需要读取完整的缓冲区来传输数据!

int read = mRecorder.read(mBuffer, 0, 256); /* Or any other magic number */
if (read>0) {
    mPlayer.write(mBuffer, 0, read);  
}

这将大大减少您的延迟。如果mHz是44100并且你处于256的MONO配置,你的延迟将不小于1000 * 256/44100毫秒= ~5.8 ms。 256/44100是从样本到秒的转换,因此乘以1000会得到毫秒。 问题是玩家的内部实施。你无法从java控制它。希望这有助于某人:)