I had this problem because I wanted to edit M4A files containing AAC audio data. I wanted to be able to merge them and add silence as padding. Due to the difference in the number of milliseconds per frame across different devices, I decided to mute the microphone and record a second of silence, then repeat that over and over whenever I needed to pad silence. (M4A + AAC silence is MUCH more complicated than raw PCM).
Unfortunately, I ran into many muting differences across Android devices. Here is what I learned:
- Muting will silently fail unless you use the MODIFY_AUDIO_SETTINGS permission. No error message, it just won't mute
- The Samsung Galaxy Tab 10.1 and Motorola Xoom work as you would expect. Call audioManager.setMicrophoneMute(true) to mute and audioManager.setMicrophoneMute(false) to unmute
- The HTC Inspire (with CyanogenMod 7) and Motorola Droid X will incorrectly return true to audioManager.isMicrophoneMute, but will not actually be muted. To fix this, before you mute, call audioManager.setMode(AudioManager.MODE_IN_CALL). Make VERY sure to change the mode back to what it was originally once you are done muting--I'm not certain, but it looked like there may be issues in other apps if you leave it set on the incorrect mode.
- The HP Touchpad, hacked to dualboot to CyanogenMod 7, does not like muting at all. It produces useless recording files, and calls to audioManager.setMode() take five seconds to return.
- The HTC MyTouch 4G claims it is muted, but will not mute itself under any conditions that I can find.
- The HTC Flyer will mute, but as soon as you call mediaRecorder.start() or mediaRecorder.stop() it will unmute itself. You can mute it again, but may catch a fraction of a second of sound first.
- Gingerbread devices, whether you want them to or not, will have between half a second and a second of silence at the beginning of any MediaRecorder recording. The overall recording is the correct length, this first part is just silenced instead of capturing what the microphone was receiving at the time.
In my case, to generate a silence file with the appropriate number of millis per frames the given device uses (so it is compatible when merging with other audio files), I use code similar to this:
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int oldAudioMode = audioManager.getMode();
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setMicrophoneMute(true);
MediaRecorder mediaRecorder = new MediaRecorder();
int bitRate = 1000 * 160;
mediaRecorder.setAudioEncodingBitRate(bitRate);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(silenceFile.getAbsolutePath());
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioSamplingRate(44100);
try {
mediaRecorder.prepare();
} catch (IOException ioe) {
throw new RuntimeException("could not prepare mediarecorder to create silence file",ioe);
}
mediaRecorder.start();
audioManager.setMicrophoneMute(true); //re-mute for devices like HTC Flyer that unmute
try {
Thread.sleep(SILENCE_LENGTH_MILLIS);
} catch (InterruptedException ie) {
throw new RuntimeException("could not record silence file", ie);
}
mediaRecorder.stop();
audioManager.setMicrophoneMute(false);
audioManager.setMode(oldAudioMode);
int currentVersion = android.os.Build.VERSION.SDK_INT;
if (currentVersion <= android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
//cut out beginning half second and use that, since it's always silent on Gingerbread
} else {
//Honeycomb and up
//Take end of audio and use that--if the device unmuted itself there may be a little noise at the beginning
}
Is this a complete solution? No. Some devices just will NOT mute. Other devices, like the previously mentioned HP Touchpad, cause all new problems if you even attempt to mute. Hopefully these tips will at least help people mute on a majority of Android devices.