[Nexus 5 Android Development] chdloc:
Assisted Manual Gain Control (aMGC) for Android 5.0.x

The Problem

By default, the microphone setup used for camcorder recordings is tuned to be fairly sensitive. The idea is that distant sources are still recorded with sufficient level. The disadvantage is that loud signals, such as music or screaming kids, will cause a great deal of distortions, thereby rending recordings in noisy environments virtually useless. Android does not offer any way to adjust the microphone gain by the user.

In looking into this issue, I have played around with automatic gain control (AGC) as offered by a webRTC component that ships with Android. I found that AGC as implemented (optimized for speech signals) is not suitable for camcorder recordings as it more often than not causes wild swings of level fluctuations.

An attempt to arrive at a solution

The idea as implemented in this app is to show a UI with gain control during a camcorder recording along with a VU meter to assist the user to adjust the gain during a particular recording. I'm calling this approach assisted manual gain control (aMGC).

The attached apk for aMGC has been generated directly from a Tasker project by using the Tasker App Factory app.

I can also post the Tasker project itself, if desired.. (Update: attached corresponding Tasker project, CamcorderMGC.prj.xml.gz)

Note that the minimum API level for this app is 21. Hence, it is only compatible with Android 5.0.x

The app does the following:

pretty much nothing if you click on the icon, as it is a service that starts automatically on boot. However, you may need to start it manually in case Android decides to kill it.

it kicks in whenever the Google Camera launches

it observes the state of the soundcard; if the microphone is opened (i.e. a camcorder recording is started), it displays a small floating and blocking UI in the lower right-hand corner of the screen with which the microphone gain can be adjusted

it uses the LED to display a VU meter, going from faint green (very low signal level detected) to yellow to orange to red (very high signal level detected)

by default it uses the gain as defined in mixer_paths.xml (indicated as 0 dB in the UI). Each short-press on the "down" button decreases the microphone gain by 6dB; a long-press decreases the gain by 12 dB; similarly each press on the "up" button increases the gain by 6 dB and a long-press by 12 dB. Additional gain is limited to +12 dB

Whenever a recording is stopped, the UI disappears and the LED VU meter stops. When the record button is pressed again, everything starts over again with the default values from mixer_paths.xml. Note that it is an Android implementation detail that mixer_paths.xml edits need a system reboot to be applied.

Prerequisites

latest "advanced" camcorder audio mod available here

tinymix (attached; uncompress, copy to /system/bin, and make executable)

NEW: all attached shell scripts, see shell_scripts.tar.gz; unpack, create a directory /data/local/tmp/camera, copy all scripts to that directory, and make all files executable. I had originally thought that Tasker automatically incorporates all shell scripts into the apk, but it does not. Currently, aMGC expects these files to reside in /data/local/tmp/camera . I'll try to fix that in a future revision of the app, by integrating the shell scripts into Tasker.

app needs root privileges

busybox

app needs Accessibility permissions. After installation go to Settings->Accessibility and enable CamcorderMGC. Unfortunately, this permission is required to detect Camera start/stop events. Don't worry, I'm not doing anything nasty

Android >= 5.0.0

If you are using Tasker (also needs Accessibility privileges) you need to run at least version v4.6. Running the attached Tasker project, i.e. CamcorderMGC.prj.xml, is generally preferred over using the app. Note that you will also need to copy the attached shell scripts to /data/local/tmp/camera when using the Tasker project.

Usage

Hit record and observe the VU meter. If the UI and VU meter do not start you may need to start the app manually as Android may have killed it.

You want the color of the LED to remain yellow/orange. Long periods of red means bad clipping. In that case you may want to lower the gain either gradually (6 dB steps) in moderately noisy environments or more aggressively (12 dB steps) in noisy environments until the LED keeps blinking yellow or orange. Short bursts of red are probably OK. I need you guys to give me feedback on that.

If the levels seem too low after a recording has been made, simply boost the gain by using a decent video editing app on your PC.

Known issues/limitation

Each interaction with the UI takes a couple of seconds to complete. Short-press or long-press the buttons once and be patient for the task to complete. Once completed, the current gain adjustment with respect to the default levels will be displayed.

aMGC currently does not work as expected when hotword detection is allowed from any screen.

Whenever the user changes the microphone gain(s) during a recording a very short click may be audible while the codec (WCD9320) changes the gains as requested. This occurs due to the discontinuity in the audio signal while the gain modification is being applied. Conventional remedies, such as cross-fading cannot be applied as the actual audio data is not available to the aMGC method. For "critical" recordings I recommend running a quick "sound check" first to find the appropriate gain and then quickly apply it at the onset of the actual recording. I suggest to be conservative with the gain as an overall low gain can be easily corrected for by post-processing while excessive gain may result in irreparable distortion.

Revision History (only the latest release is attached to this post)

01/02/2015: v0.1 (initial revision)

01/06/2015: v0.2

(hopefully) fixes non-appearing UI for some users

supports kernels other than stock that reference a slightly different device for controlling the LEDs

huge thanks go to [MENTION=1901675]adnan.selimagic[/MENTION], [MENTION=4258493]indigobv[/MENTION], and [MENTION=4136633]marquimsp[/MENTION] for alpha testing!