Android上的音频录制-长时间执行读取操作

Android上的音频录制-长时间执行读取操作,android,audio-recording,Android,Audio Recording,我有一个android应用程序,它使用AudioRecord对象录制音频,并通过通知获取数据。 我每64毫秒请求一次通知,并得到它,但有时,在某些手机上,当我从AudioRecorder对象进行实际读取时,需要几秒钟才能返回。 你知道什么会导致这样的事情吗 下面是我所做工作的概要 private void GetRecorder() { int sampleRate = 16000; int framePeriod

我有一个android应用程序,它使用AudioRecord对象录制音频,并通过通知获取数据。 我每64毫秒请求一次通知,并得到它,但有时,在某些手机上,当我从AudioRecorder对象进行实际读取时,需要几秒钟才能返回。 你知道什么会导致这样的事情吗

下面是我所做工作的概要

        private void  GetRecorder()
        {
            int sampleRate = 16000;
            int framePeriod = (int)(sampleRate * 64/ 1000);
            int bufferSize = framePeriod * 16/ 8;

            recorder = new AudioRecord(AudioSource.MIC, sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
            recorder.setPositionNotificationPeriod(framePeriod);
            recorder.setRecordPositionUpdateListener(this.mRecordListener);
        }           

        private OnRecordPositionUpdateListener mRecordListener = new OnRecordPositionUpdateListener() 
        {
            long start = System.currentTimeMillis();
            long readTime = 0;
            long maxReadTime = 0;
            int frames = 0;

            @Override
            public void onPeriodicNotification(AudioRecord local_recorder) 
            {
                int buffPos = 0;
                int framePeriod = (int)(16000 * 64 / 1000);

                long beforeRead = System.currentTimeMillis();
                int readBytes = local_recorder.read(bufferQue.pool[queLocation].audioBuffer, buffPos, Math.min(framePeriod, framePeriod - buffPos));
                long afterRead = System.currentTimeMillis();

                if (afterRead - beforeRead > maxReadTime) maxReadTime = afterRead - beforeRead;
                readTime += afterRead - beforeRead;

                //This section each 10 secs if didn't get enough frame and print the data
                frames++;
                if (System.currentTimeMillis() - start  > 10000)
                {
                  if (frames < 110)
                  {
                      log4j.info("In last 10 secs: " + frames + ", read time was " + readTime + " Max read time was " + maxReadTime);
                  }
                  readTime = 0;
                  maxReadTime = 0;
                  frames = 0;
                  start = System.currentTimeMillis();
                }
             }

            @Override
            public void onMarkerReached(AudioRecord recorder) {
            }

        };
private void GetRecorder()
{
int-sampleRate=16000;
整数帧周期=(整数)(采样率*64/1000);
int bufferSize=framePeriod*16/8;
记录器=新的音频记录(AudioSource.MIC、sampleRate、AudioFormat.CHANNEL\u单声道、AudioFormat.ENCODING\u PCM\u 16位、bufferSize);
recorder.setPositionNotificationPeriod(帧周期);
setRecordPositionUpdateListener(this.mRecordListener);
}           
私有OnRecordPositionUpdateListener mRecordListener=新OnRecordPositionUpdateListener()
{
长启动=System.currentTimeMillis();
长读取时间=0;
长maxReadTime=0;
int帧=0;
@凌驾
公共无效的定期通知(本地录音机)
{
int-buffPos=0;
整数帧周期=(整数)(16000*64/1000);
long beforeRead=System.currentTimeMillis();
int readBytes=local_recorder.read(bufferQue.pool[queLocation].audioBuffer,buffPos,Math.min(framePeriod,framePeriod-buffPos));
long afterRead=System.currentTimeMillis();
如果(afterRead-beforeRead>maxReadTime)maxReadTime=afterRead-beforeRead;
读取时间+=读后-读前;
//如果没有获得足够的帧并打印数据,则每10秒执行一次此部分
frames++;
如果(System.currentTimeMillis()-start>10000)
{
如果(帧<110)
{
log4j.info(“在最后10秒:“+frames+”,读取时间为“+readTime+”,最大读取时间为“+maxReadTime”);
}
readTime=0;
maxReadTime=0;
帧=0;
start=System.currentTimeMillis();
}
}
@凌驾
MarkerReached上的公共空白(录音机){
}
};
local_recorder.read(bufferQue.pool[queLocation].audioBuffer,buffPos,Math.min(framePeriod,framePeriod-buffPos))

read是一种阻塞方法—它将阻塞线程(在您的情况下是主线程),直到有足够的数据填充请求的buffersSize—解决方案是在辅助线程中执行读取。把我在上面写的那一行放在一个线程里——就是这样


你要求:“给我64毫秒的录音”。回答:“好的,但是等我有足够的数据时再说。可能是小故障、外面的暴风雨等,所以你必须等待……”。结论:做一个工作线程来等待它。Resume thread->read done->pause thread->Resume from the listener,->et

如果您在API级别>=23的物理设备上进行测试,那么read函数需要四个参数。。最后一个选项是设置READ_阻塞或READ_非阻塞