Search code examples
javaandroidaudiologcataudiorecord

Android AudioRecord failing when calling the startRecording() method


I'm trying to record audio in android and store it in an array of bytes, and for that I use Android's AudioRecord built-in class.
I've already used this class before, and all was good, but for some reason, it seems the AudioRecord won't work anymore.

The problem is that the AudioRecord gets initialized and shows no errors, but when it's time to actually record something, by calling its' startRecording() method, something is failing and I don't even get a proper reason why.

This is ALL the output from Logcat after calling this method:

01-18 18:54:49.545  11303-11338/com.mypackage E/android.media.AudioRecord﹕ MediaRecorder prepare   CallingPid =  11303  Callinguid=  10128

01-18 18:54:49.545  11303-11338/com.mypackage E/android.media.AudioRecord﹕ java.lang.Throwable
        at android.media.AudioRecord.startRecording(AudioRecord.java:631)
        at mypackage.AudioRecorder.record(AudioRecorder.java:179)

Of course no audio gets recorded after that, for those wondering if it's just an internal error message.

This is the code for initializing the AudioRecord class:

int bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, RECORDER_CHANNEL, RECORDER_AUDIO_ENCODING);

        if (bufferSize != AudioRecord.ERROR_BAD_VALUE && bufferSize > 0)
        {
            // check if we can instantiate and have a success
            AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, AUDIO_SAMPLE_RATE, RECORDER_CHANNEL,
                    RECORDER_AUDIO_ENCODING, bufferSize);

            if (recorder.getState() == AudioRecord.STATE_INITIALIZED)
            {
                m_Recorder = recorder;
                m_RecordingThread = Executors.newSingleThreadExecutor();
                m_IsInitialized = true;
                return;
            }
        }

When the constants that are used are:

/**
 * Recorded audio's sample rate.
 */
private static final int AUDIO_SAMPLE_RATE = 44100;

/**
 * Recorded audio's channel.
 */
private static final int RECORDER_CHANNEL = AudioFormat.CHANNEL_IN_MONO;

/**
 * Recorded audio's encoding.
 */
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

The error is happening here:

if (m_Recorder != null)
            m_Recorder.startRecording();

So after seeing this happen a couple of times, I decided to go deeper and try to debug it, going as deep as I can, to the source of error in the AudioRecord class itself, using Jetbrain's decompiler.
For some strange reason, as soon as the app hit the breakpoint located at the source of error, the next step-over couldn't be completed, as the AudioRecord has crashed yet again, with the same error message.

The next step for me was creating a sample project just to test AudioRecord's functionality, but this time I added an AudioTrack as well, that will output all my recordings instantly (a kind of a loopback), in case the AudioRecord class manages to record something, with or without the error.
And so the magic has happened - The app is working, AudioRecord is recording, and AudioTrack is playing.
It seemed really strange that the AudioTrack class suddenly resolved all my issues, so I removed it from my code and tried running the app yet again.
This time, the AudioRecord worked without all problems, and even though I couldn't hear its' output, I can assure you it has been recording.

With a bit of relief, I thought to my myself that I've finally overcame this issue, and I'm ready to move forward, so I added some extra code to encode and decode the recorded audio data.
To hear an output, I returned the code using the AudioTrack class, and ran the app.

Wanna hear a funny thing? The app has crashed with the same error, AGAIN.

Now theoretically the problem could be not releasing the AudioRecord instance when done using it, but I've covered that too from the very beginning.

I've tried looking practically everywhere on the internet for a solution, but it seems as if no one has even encountered a problem like this before.

Also, I'd like to point out that I've tried resetting my device, the ADB plugin, and rebuilding all projects.

I'm using a Meizu MX5 phone, with Android Lollipop(API 21).


Solution

  • Well, I solved the problem, or at least a part of it, causing it to work now. The thing is I tried to read more bytes than the size of my pre-allocated buffer, upon calling the read() method of the AudioRecord class.
    Although it didn't solve the main issue of this post, which is the strange error message and the uncaught exception, it made the AudioRecord work perfectly, so for me this thread can be seen as answered and closed!