android,AudioRecord.read() - > bufferoverflow,如何处理缓冲区?

时间:2011-03-07 11:01:36

标签: android audiorecord

我的教授是一个大学项目。想让我写一个Android应用程序,将是我的第一个。我有一些Java经验,但我是Android编程的新手,所以请温柔地对待我。

首先我创建一个Activity,其中只有两个按钮,一个用于启动AsyncTask,另一个用于停止它,我的意思是我只是将布尔值“isRecording”设置为false,其他所有内容都在AsyncTask中处理,后者附加了作为源代码。

事情运行得很好,但过了一会儿我可以在LogCat中找到一些缓冲区溢出消息,之后它会因未捕获的异常而崩溃。我弄清楚它为什么会崩溃,未捕获的异常不应该是那个问题的目的。

03-07 11:34:02.474: INFO/buffer 247:(558): 40
03-07 11:34:02.484: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.484: INFO/MutantAudioRecorder:doInBackground()(558): isRecoding
03-07 11:34:02.494: WARN/AudioFlinger(33): RecordThread: buffer overflow
03-07 11:34:02.494: INFO/buffer 248:(558): -50
  1. 我正如你所看到的那样写出了缓冲区,但不知怎的,我认为我在正确配置AudioRecord时犯了一个错误,任何人都可以告诉我为什么会得到缓冲区溢出?

  2. 接下来的问题是,我该如何处理缓冲区?我的意思是,我有里面的值,并希望它们在屏幕上以图形频谱图显示。有没有人有这方面的经验,我可以提一下吗?我怎么能继续......

  3. 提前感谢您的帮助。

    AsyncTask的源代码:

    package nomihodai.audio;
    
    import android.media.AudioFormat;
    import android.media.AudioRecord;
    import android.os.AsyncTask;
    import android.util.Log;
    
    
    
    public class MutantAudioRecorder extends AsyncTask<Void, Void, Void> {
    
    private boolean isRecording = false;
    public AudioRecord audioRecord = null;
    public int mSamplesRead;
    public int buffersizebytes;
    public int buflen;
    public int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
    public static short[] buffer;
    public static final int SAMPLESPERSEC = 8000;
    
    
    @Override
    protected Void doInBackground(Void... params) {
    
        while(isRecording) {
    
            audioRecord.startRecording();
            mSamplesRead = audioRecord.read(buffer, 0, buffersizebytes);
    
            if(!readerT.isAlive())
                readerT.start();
    
            Log.i("MutantAudioRecorder:doInBackground()", "isRecoding");
        }
    
        readerT.stop();
    
        return null;
    }
    
    
    Thread readerT = new Thread() {
        public void run() {
            for(int i = 0; i < 256; i++){ 
                Log.i("buffer " + i + ": ", Short.toString(buffer[i]));
            }
        }
    };
    
    
    @Override
    public void onPostExecute(Void unused) {
        Log.i("MutantAudioRecorder:onPostExecute()", "try to release the audio hardware");
    
        audioRecord.release();
    
        Log.i("MutantAudioRecorder:onPostExecute()", "released...");
    }
    
    
    public void setRecording(boolean rec) {
        this.isRecording = rec;
    
        Log.i("MutantAudioRecorder:setRecording()", "isRecoding set to " + rec);
    }
    
    
    @Override
    protected void onPreExecute() {
    
        buffersizebytes = AudioRecord.getMinBufferSize(SAMPLESPERSEC, channelConfiguration, audioEncoding);
        buffer = new short[buffersizebytes];
        buflen = buffersizebytes/2;
    
        Log.i("MutantAudioRecorder:onPreExecute()", "buffersizebytes: " + buffersizebytes
                                                    + ", buffer: " + buffer.length
                                                    + ", buflen: " + buflen);
    
        audioRecord = new AudioRecord(android.media.MediaRecorder.AudioSource.MIC,
                SAMPLESPERSEC,
                channelConfiguration,
                audioEncoding,
                buffersizebytes);
    
        if(audioRecord != null)
            Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord object created");
        else
            Log.i("MutantAudioRecorder:onPreExecute()", "audiorecord NOT created");
    }
    

    }

2 个答案:

答案 0 :(得分:4)

可能有一些实时分析过程处理录制的音频字节?

由于记录的缓冲区大小有限,一旦“分析过程”慢于记录速率,缓冲区中的数据将被卡住,但记录字节总是来临,因此缓冲区溢出。

尝试在录制时使用线程,在记录的字节上使用其他进程,这种方法有一个开源示例代码:http://musicg.googlecode.com/files/musicg_android_demo.zip

答案 1 :(得分:0)

正如我们在聊天室中讨论的那样,解码音频数据并将其显示在屏幕上应该很简单。你提到音频缓冲区每秒有8000个样本,每个样本是16位,它是单声道音频。

显示这一点应该很简单。在视图中将每个样本视为垂直偏移。您需要将-32k到+ 32k的范围缩放到视图的垂直高度。从视图的左边缘开始,每列绘制一个样本。到达右边缘时,再次环绕(根据需要删除上一行)。

这将最终将每个样本绘制为单个像素,这可能看起来不太好。您还可以在相邻样本之间绘制一条线。您可以使用线宽,颜色等来获得最佳效果。

最后一个注意事项:您将每秒绘制8000次,加上更多以清除之前的样本。您可能需要采取一些快捷方式来确保帧速率能够跟上音频。您可能需要跳过样本。

相关问题