Android 由于pcm_read()在Galaxy S4上返回错误n-5,获取缓冲区超时

Android 由于pcm_read()在Galaxy S4上返回错误n-5,获取缓冲区超时,android,samsung-mobile,audiorecord,Android,Samsung Mobile,Audiorecord,我有一个应用程序,它使用AudioRecord API在Android设备上捕获音频,但在Galaxy S4设备上多次失败。这也发生在尝试同时使用AudioRecord和MediaRecorder录制音频的其他应用程序中(例如AudioRec HQ)。我能够使用下面的代码在测试应用程序中复制它: final int bufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.EN

我有一个应用程序,它使用AudioRecord API在Android设备上捕获音频,但在Galaxy S4设备上多次失败。这也发生在尝试同时使用AudioRecord和MediaRecorder录制音频的其他应用程序中(例如AudioRec HQ)。我能够使用下面的代码在测试应用程序中复制它:

final int bufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize << 2);
mAudioRecord.startRecording();

mRecordThread = new Thread(new Runnable() {
    @Override
    public void run() {
        BufferedOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new BufferedOutputStream(new FileOutputStream(String.format(Locale.US, "/sdcard/%1$d.pcm", System.currentTimeMillis())));
            final byte[] buffer = new byte[bufferSize];
            int bytesRead;
            do {
                bytesRead = mAudioRecord.read(buffer, 0, buffer.length);
                if (bytesRead > 0) {
                    fileOutputStream.write(buffer, 0, bytesRead);
                }
            }
            while (bytesRead > 0);
        } catch (Exception e) {
            Log.e("RecordingTestApp", e.toString());
        }
    }
});
mRecordThread.start();
以下是完整的日志:

发生这种情况时不会引发异常,AudioRecord.read会一直阻塞,直到硬件恢复并再次开始录制,但会丢失2-4秒的音频数据,因此用户非常恼火,因为他们的音频文件丢失了大量区域,而没有解释原因

这是一个已知的硬件问题,还是我应该做一些不同的事情来更可靠地记录?
有没有办法检测到这个问题已经发生了

我手头没有银河系,但我发现你的例子有几个地方不对劲

new AudioRecord(MediaRecorder.AudioSource.VOICE_RECOGNITION, 8000,
首先,在8000 Hz的采样频率下初始化音频记录。根据文件,只有44100是保证可用的。8000赫兹的采样器可能根本不存在。因此,您应该检查录音是否处于正确的状态。即:

mAudioRecord.getState()==STATE_INITIALIZED
您可能还需要检查getMinimumBufferSize的返回。如果是错误值,则传递的参数不正确

然后,一旦完成,您可能希望在将读取数据的线程内开始记录。这很可能不是问题的原因,但当发生溢出时,音频驱动程序会发生什么情况通常不清楚。例如:如果读取速度不够快,硬件可能会产生太多数据。通常情况下,根据制造者的不同,alsa Drvier的行为也会有所不同。因此,为了避免这个问题,最好在开始录制之前直接编写startRecording,因此在本例中,在runnable中

完成后,您可能需要检查

mAudioRecord.getRecordingState()==RECORDING_RECORDING
如果没有录音,那么司机已经告诉你有问题了

完成录制后,还应停止设备。同样,如果您自己不关闭某些alsa驱动程序,它们会有一个关闭超时,这意味着下次尝试打开它们时,您可能根本无法访问它们(这当然是Linux特有的)

因此,乍一看,这些是我将采取的途径,我的猜测是,组合采样器/通道配置是不可用的


最后,我还感觉到参数VOICE_RECOGNITION可能已关闭。也许用默认值替换它。过去我自己也遇到过一些问题。

在使用AudioRecord和MediaRecorder尝试了各种频率、缓冲区大小和音频源以及多种格式后,如果没有这些pcm错误,我无法录制音频。我从play store下载的几个录音应用程序也会出现同样的错误


我遵循这一点创建了一个OpenSL ES jni库,它一直运行良好,我将向任何在Galaxy S4上看到这些错误的人推荐这种方法,仅使用四倍于最小缓冲区大小的方法可能不足以解释写入输出时可能出现的延迟。既然您只是在“磁盘”上录制,而没有执行低延迟要求的操作,为什么不使用更大的缓冲区呢?
mAudioRecord.getRecordingState()==RECORDING_RECORDING