AudioRecord: buffer overflow?
Asked Answered
W

2

8

I'm getting buffer overflow while RECORDING with my app. The recording is performed in a Service. I could not figure out why I'm getting this message from AudioFlinger.

Below I instantiate the AudioRecord object and set it's callbacks.

bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
aRecorder = new AudioRecord(audioSource, sampleRate, channelConfig, audioFormat, bufferSize);

aRecorder.setRecordPositionUpdateListener(updateListener);

bytesPerSample = bitsPerSample / 8;
int bytesPerFrame = nChannels * bytesPerSample;
framePeriod = bufferSize / bytesPerFrame; // nr of frames that can be kept in a bufferSize dimension    
int result = aRecorder.setPositionNotificationPeriod(framePeriod);    
buffer = new byte[bufferSize];

The audioRecord callback:

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener(){
        public void onPeriodicNotification(AudioRecord recorder){
            int result = aRecorder.read(buffer, 0, buffer.length);
        }

        public void onMarkerReached(AudioRecord recorder)
        {}
    };

I suspect the problem is related to the:aRecorder.setPositionNotificationPeriod(framePeriod); - maybe the period is too big for this bufferSize and a faster(smaller) period will solve the issue.

Could someone tells me how to get rid of the buffer overflow?

Wiliness answered 22/7, 2013 at 14:49 Comment(0)
Y
10

To fix that issue, change the buffer size of AudioRecord to 2 times the minimum buffer size.

You can use AudioRecord.getMinBufferSize() static method. This will give you the minimum buffer size to use for your current format.

The syntax of getMinBufferSize() method is:

public static int getMinBufferSize (
    int sampleRateInHz, int channelConfig, int audioFormat)

Anything less than this number will result in failure while creating the AudioRecord object.

You should have been reducing the buffer size, so as not to overwhelm the audio subsystem with demands for data.

Remember to put the overridden methods (@Override) for audioRecord callback as follows:

private AudioRecord.OnRecordPositionUpdateListener updateListener = new AudioRecord.OnRecordPositionUpdateListener(){

        @Override
        public void onPeriodicNotification(AudioRecord recorder){
            int result = aRecorder.read(buffer, 0, buffer.length);
        }

        @Override
        public void onMarkerReached(AudioRecord recorder)
        {}
    };

I recommend to read the post: Android audio recording, part 2

One more thing that you could try is to use threads on recording and the other process on the recorded bytes, thus avoiding too much overload on the main UI thread.

The open source sample code for this approach: musicg_android_demo

Check this post for more - android-audiorecord-class-process-live-mic-audio-quickly-set-up-callback-func

Yoga answered 26/7, 2013 at 8:40 Comment(6)
Thanks for your answer, all data processing is done in a secondary thread. bufferSize is taken using the static method od AudioRecord(getMinBufSize). the @overwrite was indeed missing.Wiliness
and I tried yesterday to multiply minBufSize with 2, but was just reducing the frequency of "BufferOverlow" msg to ~30 sec. Anyway, multiplying with 2 was until now the best variant I tried, but I want to get rid of it completely, since my recording stops after 1:3 hours.Wiliness
So that means after multiplying with 2, there is no buffer overflow problem but the recording is stopping after certain amount of time ? You could try to reset recorder before releasing it.Yoga
No, after multiplying with 2 the overflow still remains, but reduced from each ~10 seconds to ~30 sec and the recording stops now after 1 hour (previous was stopping after 20 min). The release/record is done in a proper manner I think.Wiliness
I've solve it by using a thread for polling the data from AudioRecord and dropping callback, just like in musicg_android_demo. I managed to record 2 hours without stopping. I will do more tests and will give you +50 bounty if everything is OK.Wiliness
@AlexandruCircus could you share your solution?Sumter
B
2

Thats because :

framePeriod = bufferSize / bytesPerFrame;

You need to multiply and not divide your buffersize.

Try with :

framePeriod = bufferSize * bytesPerFrame;

And if you need a sample : here is a complete audio capture class

hope it helps

Bascomb answered 26/7, 2013 at 8:37 Comment(2)
thanks. The buffer should be instantiated as follows: buffer = new byte[framePeriod * bytesPerFrame] ?Wiliness
I will try to follow the link you provided. I saw there it uses a secondary thread to record instead of the callback variant(onPeriodicNotification)Wiliness

© 2022 - 2024 — McMap. All rights reserved.