0

我有一个 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) {
            }

        };
4

2 回答 2

1

如果您在 API 级别 >=23 的物理设备上进行测试,则读取函数需要四个参数。最后一个是设置 READ_BLOCKING 或 READ_NONBLOCKING 的选项。

于 2015-11-12T17:47:50.090 回答
0

local_recorder.read(bufferQue.pool[queLocation].audioBuffer, buffPos, Math.min(framePeriod, framePeriod - buffPos));

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

您要求:“给我 64 毫秒的录音”。回答:“好的,但是等我有足够的数据。可能是故障,外面暴风雨等,所以你必须等待......”。结论:做一个工作线程来等待它。恢复线程-> 读取完成-> 暂停线程-> 从侦听器再次恢复,-> 等

于 2014-04-07T19:36:30.273 回答