I'm currently starting writing a software for Android which is about to measure the reverberation time of closed rooms.
I had to choose AudioRecord instead of MediaRecorder because it gives me the chance to get the raw data.
You may know that there are many different constant to choose from for the AudioFormat (e.g.: CHANNEL_IN_MONO, CHANNEL_IN_STEREO, CHANNEL_IN_PRESSURE) and you may know that in android smartphones there are more than just one microphone embedded (usually you have 2 microphones in it, in order to have noise cancellation and stuff like that).
Here comes the question: Which constant do I have to choose to be sure that only just ONE microphone is giving me the raw data?
If you do a mono recording the device should only be recording from one microphone. I'm not sure what you mean by "raw" data. There will always be some acoustic compensation processing done (e.g. automatic gain control, equalization, etc), and this is not something that you can turn off.
One thing that also will affect the recording is which AudioSource you choose. If you select CAMCORDER on a phone with 2 or more microphones you'll typically get the back microphone with far-field tuning if you do a mono recording. If you select MIC/DEFAULT you should get the primary mic, but it may be tuned for either near-field recording or far-field recording depending on the vendor (I suspect that you'd want far-field tuning if you're trying to measure room reverberation).
Related
I'm developing an app that records audio input from the device's microphone(s). We'd like to record unprocessed/raw audio (i.e. with no effects applied like noise suppression or automatic gain control) and also give users the option to specify which microphone (e.g. top, front, back, etc.) to use for recording.
According to Android documentation, the only way to get an input audio stream that's guaranteed to be unprocessed is by selecting VOICE_RECOGNITION on setAudioSource()
That said, what would be the correct way to choose the physical microphone to use?
In more recent API levels, there are the following methods that seem to allow for the selection of specific microphones:
Android 6+: AudioRecord.setPreferredDevice() accepts a target input device to use for input. We may use AudioManager.getDevices() to get a list of available microphones, but it seems it's not possible to tell the position (front, back, etc.) of the microphones returned by that method.
Android 11+: AudioRecord.setPreferredMicrophoneDirection() receives a direction constant that specifies the "logical microphone (for processing)". That "logical microphone" seems to map well to what I'm calling a microphone's position (front, back, etc.), but I'm not sure about how this method works in conjunction with setPreferredDevice().
Does anybody know how to achieve my goals, i.e. get unprocessed audio input while also specifying the physical microphone to use?
The microphone selection is done with MediaRecorder.AudioSource.MIC (front) / MediaRecorder.AudioSource.CAMCORDER (back) / MediaRecorder.AudioSource.DEFAULT (default).
VOICE_RECOGNITION is used to enable/disable AGC but can only be used with the front microphone (MediaRecorder.AudioSource.MIC).
I’m struggling since days trying to obtain a raw audio stream from the microphone. I am trying different ways: the low-level JNI way with Oboe Library (either AAudio and OpenSL ES implementations) and the Android’s AudioRecord Java classes.
The problem I am facing is that I am not able to retrieve amplitudes near -/+1.0 while being sure of saturating the microphone input with a calibrated pure tone with such a high amplitude.
I think that the problem is that I am not able to effectively disable the signal preprocessing from AndroidOS (Automatic Gain Control or Noise Cancelling).
AutomaticGainControl.create(id).setEnabled(false)
(not working!)
Also, it seems that it is not possible also to disable any additional microphone rather than the one "selected" (done that as selecting the setPreferredDevice on AudioRecord instance). Used as audio source: unprocessed, mic, voice_recognition.
Is there anyway doing this or am I missing something?
Thank you
Which audio source are you using for your recording? VOICE_RECOGNITION or UNPROCESSED are mandated to not have any pre-processing enabled by default (i.e. see https://source.android.com/compatibility/10/android-10-cdd#5_11_capture_for_unprocessed) and therefore would allow you to check your signal path.
I'm messing around in my app with a custom model for speech commands - I have it working fine recording and processing input audio from an AudioRecord, and I give feedback to the user through text to speech.
One issue I have is that I'd like this to work even when audio is playing - either through my own text to speech or through something else playing in the background (music for instance). I realize this is going to be a non trivial problem, but if I could get access in some way to the audio output data (what the phone is playing) and match that up with my microphone input data, I think I can at least adjust my model for this + improve my results.
However, based on Android - Can I get the audio data for playback from the audio mixer? , it sounds like that is impossible.
Two questions:
1) Is there any way that I'm missing to get access to expected audio output/playback data through the android api, or any options the android api provides for dealing with this issue (the feedback loop between audio output and input)?
2) Outside of stopping all other playback or waiting for other playback to finish - is there any other approach to solve this problem? I would assume some calling apps have a way of dealing with this if the user is on speaker phone, I'm just missing how to do it myself
Thanks
Answers to 1 & 2: You want AcousticEchoCanceler.
A short lecture on why "deleting the speaker audio from the microphone input" input is a non-trivial task that takes substantial signal processing knowledge: It's more complicated than just time-shifting the speaker audio a little bit and subtracting it from the mic input. The fact is, the spectrum of the audio changes drastically even as it leaves the speaker (most tiny speakers have a very peaky response centered around 3-4KHz). The audio may bounce off multiple objects (walls, etc.) before it gets back to the mic (multipath interference). Different frequency components interfere at the microphone in different, impossible to predict ways, vastly changing the spectrum of the audio. And by the way -- if anything in the room moves, say, if you put your hand near the phone -- everything changes. That is why you don't want to try to write your own echo cancellation filter. Android has provided one for you, so you can write cool speakerphone apps and such.
I have an audio recording app on android market which records using PCM-WAV format.
My app also offers custom gain control ([-20dB, +20dB]), so I alter the original audio data with user selected gain value.
It works pretty well when using device built-in mic, but I have a user which uses some external mic plugged into his device, and the output is too loud and full of distortions (because of the loudness of his ext mic). Even when he set the gain to -20dB, the output is loud and contains distortions.
I thought I should add AGC control into the app for cases as this.
Now my question:
This AGC only applies when using DEVICE BUILT-IN mic? Or it applies also when using an ext mic plugged into the handheld?
It's quite likely that the real problem is that his microphone is overdriving the input jack - if that is the case, software can't fix the problem as what the A/D converter sees is already hopelessly distorted.
Your client may need to add an attenuator (resistive voltage divider) to the input signal.
Also, if the input signal is asymmetric it may be necessary to couple through a series capacitor to block any DC component.
Doing a recording with no gain, and examining the resulting waveform in an audio editor like audacity would probably be informative.
(Normally I would not post something this speculative as an answer, but was specificaly asked to convert it to one from its original offering as a comment)
A lot of smart phone now have more than one microphone. One for voice input and another for reducing the enviroment noise.
I am wondering how could I access the two microphone's signal independently? Or turn off one of the microphone?
Any thoughts or comments are welcomed. Thanks a lot.
I'm not familiar with the Galaxy S3 specifically, but the following is true for the majority of devices I've worked with:
There's no reliable way of selecting whether to use the primary or secondary mic for a mono recording. The MIC AudioSource usually means the primary mic when doing a mono recording, and the CAMCORDER source might mean the secondary mic. But there's no guarantee for this, because it depends e.g. on the physical placement of the mics.
Recording in mono effectively turns the other mic off, and whatever noise reduction is done uses only the signal from one mic (so there's little to no reduction of dynamic noise).
One exception to this might be if you record during a voice call where both mics already have been enabled in order to do uplink noise suppression.Another exception might be if you use the VOICE_RECOGNITION AudioSource, because some vendors apply noise suppression on the signal using one or more extra mics in this use-case.
Recording in stereo records from both mics on a 2-mic device. The left channel contains the input from one mic and the right channel contains the input from the other mic, but there's no guarantee as to which physical mic the channels correspond to (again, depends on the placement).