【问题标题】:AudioRecord: buffer overflow?AudioRecord:缓冲区溢出?
【发布时间】:2013-07-21 08:50:21
【问题描述】:

RECORDING 使用我的应用程序时出现缓冲区溢出。录制在Service 中进行。我不明白为什么我会收到来自AudioFlinger 的这条消息。

下面我实例化AudioRecord 对象并设置它的回调。

bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
aRecorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize);

aRecorder.setRecordPositionUpdateListener(updateListener);

bytesPerSample = bitsPerSample / 8;
int bytesPerFrame = nChannels * bytesPerSample;
framePeriod = bufferSize / bytesPerFrame; // nr of frames that can be kept in a bufferSize dimension    
int result = aRecorder.setPositionNotificationPeriod(framePeriod);    
buffer = new byte[bufferSize];

audioRecord 回调:

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener(){
        public void onPeriodicNotification(AudioRecord recorder){
            int result = aRecorder.read(buffer, 0, buffer.length);
        }

        public void onMarkerReached(AudioRecord recorder)
        {}
    };

我怀疑这个问题与:aRecorder.setPositionNotificationPeriod(framePeriod); 有关 - 也许这个bufferSize 的周期太大了,更快(更小)的周期将解决问题。

谁能告诉我如何摆脱缓冲区溢出?

【问题讨论】:

    标签: android buffer-overflow audiorecord android-audiorecord


    【解决方案1】:

    要解决该问题,请将 AudioRecord 的缓冲区大小更改为最小缓冲区大小的 2 倍。

    您可以使用AudioRecord.getMinBufferSize() 静态方法。这将为您提供用于当前格式的最小缓冲区大小。

    getMinBufferSize()方法的语法是:

    public static int getMinBufferSize (
        int sampleRateInHz, int channelConfig, int audioFormat)
    

    任何小于此数字的值都将导致创建 AudioRecord 对象时失败。

    您应该减少缓冲区大小,以免音频子系统因数据需求而不堪重负。

    记得将audioRecord回调的重写方法(@Override)如下:

    private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener(){
    
            @Override
            public void onPeriodicNotification(AudioRecord recorder){
                int result = aRecorder.read(buffer, 0, buffer.length);
            }
    
            @Override
            public void onMarkerReached(AudioRecord recorder)
            {}
        };
    

    我推荐阅读帖子:Android audio recording, part 2

    您可以尝试的另一件事是在录制时使用线程,在录制的字节上使用其他进程,从而避免主 UI 线程上的过多过载。

    此方法的开源示例代码:musicg_android_demo

    查看此帖子了解更多信息 - android-audiorecord-class-process-live-mic-audio-quickly-set-up-callback-func

    【讨论】:

    • 感谢您的回答,所有数据处理均在辅助线程中完成。 bufferSize 是使用静态方法 od AudioRecord(getMinBufSize) 获取的。 @overwrite 确实不见了。
    • 我昨天尝试将 minBufSize 乘以 2,但只是将“BufferOverlow”消息的频率降低到约 30 秒。无论如何,乘以 2 是迄今为止我尝试过的最好的变体,但我想完全摆脱它,因为我的录音在 1:3 小时后停止。
    • 也就是说,乘以2后,没有缓冲区溢出问题,但录制在一定时间后停止?您可以尝试在释放之前重置记录器。
    • 不,在乘以 2 后溢出仍然存在,但从每约 10 秒减少到约 30 秒,现在记录在 1 小时后停止(之前在 20 分钟后停止)。我认为发行/记录是以适当的方式完成的。
    • 我已经通过使用线程从 AudioRecord 轮询数据并删除回调来解决它,就像在 musicg_android_demo 中一样。我设法不停地录制了2个小时。我会做更多的测试,如果一切正常,我会给你 +50 赏金。
    【解决方案2】:

    那是因为:

    framePeriod = bufferSize / bytesPerFrame;
    

    您需要乘而不是除以缓冲区大小。

    尝试:

    framePeriod = bufferSize * bytesPerFrame;
    

    如果您需要样品:here is a complete audio capture class

    希望对你有帮助

    【讨论】:

    • 谢谢。缓冲区应按如下方式实例化: buffer = new byte[framePeriod * bytesPerFrame] ?
    • 我会尝试点击您提供的链接。我在那里看到它使用辅助线程来记录而不是回调变体(onPeriodicNotification)
    猜你喜欢
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 2013-11-06
    • 2013-04-11
    • 2015-07-07
    • 2012-02-05
    相关资源
    最近更新 更多