9

I have an issue using Android's MediaRecorder to record sound from microphone to .m4a files (AAC-LC, MPEG-4 container). Starting from API level 18, the default sampling rate drops from 44.1 or 48 kHz (depending on device) to only 8 Hz. If I specify the sampling rate using MediaRecorder.setAudioSamplingRate, it uses the specified rate but there are a lot of strange noise in the recording.

In LogCat, the following warning are happening from time to time:

(1) Tag: AudioSource Text: AudioRecord reported overrun

(2) Tag: AudioFlinger Text: RecordThread: buffer overflow

Here's the code:

MediaRecorder recorder = new MediaRecorder();
recorder.setAudioChannels(2);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioSamplingRate(48000);   // if not specified, defaults to 8kHz, if specified 44.1 or 48 kHz, lots of noise
recorder.setOutputFile("test.m4a");

try {
    recorder.prepare();
    recorder.start();

} catch (IOException ioe) {
    Log.e(TAG, "IOException", ioe);
} catch (IllegalStateException ise) {
    Log.e(TAG, "IllegalStateException", ise);
} catch (Exception e) {
    Log.e(TAG, "Exception", e);
}

Any help is greatly appreciated.

  • Why are you setting the number of audio channels to 2 when recording from the microphone? – Squonk Mar 15 '15 at 08:35
  • Good point Squonk, thanks, but it doesn't mattter. Even if I use 1 audio channel, the problem is still there. One more finding though, in LogCat I see the following 2 warning happening from time to time: (1) AudioSource - AudioRecord reported overrun (2) AudioFlinger - RecordThread: buffer overflow –  Mar 16 '15 at 03:01
  • Experiment with diff encoders and rates ( 22050, 16000 ). Codecs listed in android docs "media formats" – Robert Rowntree Mar 16 '15 at 03:49
  • @Justin : Yep, buffer overruns / overflows are likely to cause samples to be dropped resulting in weird results. Sometimes not too bad with MP3 but MP4 audio can really get messed up. – Squonk Mar 16 '15 at 08:22
  • @Robert - thanks. Tried experimenting different sampling rates, had similar problem of the noise. Looks like whenever I specified a sampling rate other than the default (8kHz), the buffer overflow and hence the noise will occur. –  Mar 18 '15 at 04:34
  • @Squonk - thanks. Agreed mp4 is more affected by this problem. I hope someone would know the reason of this and also how to make a good quality recording using Android :) –  Mar 18 '15 at 04:36
  • @Justin : Have you tried experimenting with `setAudioEncodingBitRate(...)`? – Squonk Mar 18 '15 at 08:15
  • https://github.com/midnightskinhead/audioboo-android/blob/master/src/fm/audioboo/application/FLACRecorder.java try flac from some git project – Robert Rowntree Mar 18 '15 at 08:17
  • @Squonk - thanks, tried but didn't help unfortunately :( –  Mar 23 '15 at 06:23
  • @Robert - tried flac, works great, unfortunately I need m4a and not flac, but that further made me think the MediaRecorder is buggy –  Mar 23 '15 at 06:24
  • Ok. so what about run "AudioRecord" @ AudioFormat.ENCODING_PCM_16BIT , 22050, AudioFormat.CHANNEL_IN_MONO then transform to audio.codec=AAC per the reqmt for "m4a" . i dont understand what is causing the overflows? – Robert Rowntree Mar 23 '15 at 15:36
  • experiencing the same issue with MediaRecorder. Any update on the fix or any improvement ? – MiaN KhaLiD Jun 10 '15 at 13:31

2 Answers2

3

After a long research and tries, this is the best working solution I made:

mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setAudioEncodingBitRate(384000);
mRecorder.setAudioSamplingRate(44100);
Ali Obeid
  • 141
  • 7
  • 1
    If only there were some way to enquire of the device what it's true hardware sampling rate was, so you could sanely choose 44100 vs 48000 without having to look up the list at http://audiobuffersize.appspot.com/ which is compiled from the app https://play.google.com/store/apps/details?id=com.levien.audiobuffersize – karora Aug 05 '17 at 11:58
  • Woah, it's a big list! and yeah I wish if someone can find the code to that! OR, someone can do a library which contains an array of model devices with each Sample Rate, and based on the phone that is launching the app it can set it up from the array right? – Ali Obeid Aug 05 '17 at 21:25
2

You can set both the SamplingRate (as you have done) and the EncodingBitRate, which you have omitted.

I have been able to achieve very high quality recordings using the following:

    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
    mRecorder.setAudioSamplingRate(48000);
    mRecorder.setAudioEncodingBitRate(384000);

This will encode with 8 bits per sample, which is probably beyond the available quality of the microphone on most devices.

karora
  • 1,223
  • 14
  • 31
  • But this is making a very noisy sound, it's like OVER high sound – Ali Obeid Jul 18 '17 at 11:31
  • I've not had that experience at all, and I've used this code on a reasonable range of devices. Perhaps some devices have a problem with it? Have you tried adjusting either (a) 48000 to 44100, and / or (b) 384000 to 160000 – karora Jul 21 '17 at 16:05
  • Well, probably.. but check my answer down, its working 100%! – Ali Obeid Jul 21 '17 at 19:42
  • Yeah, it's possible that some hardware supports 44100 better than 48000. It's certainly something I used to see quite commonly on Linux a few years ago, but I'd thought by now it would all be a distant memory. What hardware are you working with? – karora Jul 21 '17 at 22:58
  • Some interesting info on here about choosing the sampling rate: https://developer.android.com/ndk/guides/audio/sampling-audio.html – karora Jul 21 '17 at 23:01
  • For me, I am testing it on Galaxy Note 4, Grand Prime, Samsung A5(2017) It's working perfectly – Ali Obeid Jul 22 '17 at 17:59