Reputation: 71
I have an android application that records audio with the AudioRecord object and gets the data via the notifications. I request a notification every 64ms, and gets it, but from time to to time, on some of the phones when I do the actual read from the AudioRecorder object, it takes it few seconds to return. Any idea what might lead to such a thing?
Below is a skeleton of what I do.
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) {
}
};
Upvotes: 0
Views: 643
Reputation: 11
if you are testing on a physical device with API level >=23 then the read function takes four parameters .. the last one being the option of setting READ_BLOCKING or READ_NONBLOCKING.
Upvotes: 1
Reputation: 5538
local_recorder.read(bufferQue.pool[queLocation].audioBuffer, buffPos, Math.min(framePeriod, framePeriod - buffPos));
read is a blocking method - it will block the thread (main thread in your case) until there are enough data to fill your requested buffersSize - solution is to perform the read in a secondary thread. Put the line I wrote above in a thread - that's it.
You requested: "give me 64 ms of recording". answer:"Ok, but wait until I have enough data. It might be glitches, storming outside, etc, so you will have to wait..." . Conclusion: do a worker thread to wait for it. Resume thread -> read done -> pause thread -> resume again from the listener, -> et
Upvotes: 0