[Nexus 5 Android Development] chdloc:
Enabling sidetone for telephony

This small, but in my opinion very useful, mod of mixer_paths.xml has absolutely nothing to do with the camcorder, but with making phone calls. I'm detailing the mod here as it will eventually end up in a future update of my camcorder audio mod.

Enabling sidetone for headphone/headset use case

This mod enables sidetone [1][2] when making a phone call while wearing headphones or headsets [3]. Sidetone is the technique of feeding an attenuated version of the microphone signal back to the loudspeaker without any noticeable delay. Added delay would cause the user to perceive sidetone as annoying echo. Why would sidetone be useful? In one word: occlusion. I just purchased a nice set of IEM (in-the-ear monitor) headphones. One common property of IEMs is that they seal the ear canal. As a result, environmental noise is - in most instances passively - suppressed by 20 dB or more. When you make a phone call while wearing one of these your own voice gets attenuated as well and it sounds very unnatural to you. To get an idea how it sounds, hold your hands over your ears and talk. Very annoying to conduct a longer conversation like this. A solution to this problem is sidetone, which is enabled by this mod. I was actually surprised to find out that the Nexus 5 does not enable sidetone in any configuration. Inexplicably, sidetone even seems to be virtually absent in modern mobile phones, but has been used extensively in enterprise and "legacy" telephony for decades (for very good reasons).

Required mixer_paths.xml edits

In your mixer_paths.xml file, exchange the "voice-headphones" device path:

<path name="voice-headphones">
<path name="headphones" />
<ctl name="HPHL Volume" value="20" />
<ctl name="HPHR Volume" value="20" />
<ctl name="RX1 Digital Volume" value="84" />
<ctl name="RX2 Digital Volume" value="84" />
</path>

with the following

<path name="voice-headphones">
<!-- the stock voice-headphone setup only calls the headphones path below and sets the gains on the bottom -->
<!-- <path name="headphones" /> -->

<ctl name="CLASS_H_DSM MUX" value="DSM_HPHL_RX1" />
<ctl name="HPHL DAC Switch" value="1" />

<!-- the filter coefficients seem to be represented in Q28 format, i.e. 1.0 corresponds to 268435456 -->
<!-- this seems to be implementing cascaded direct-form I biquad IIR filters: -->
<!-- y[n] = b_0*x[n] + b_1*x[n-1] + b_2*x[x-2] - a_1*y[n-1] - a_2*y[n-2] -->
<ctl name="IIR1 Band1" id ="0" value="268435456" />
<ctl name="IIR1 Band1" id ="1" value="0" />
<ctl name="IIR1 Band1" id ="2" value="0" />
<ctl name="IIR1 Band1" id ="3" value="0" />
<ctl name="IIR1 Band1" id ="4" value="0" />
<ctl name="IIR1 Band2" id ="0" value="268435456" />
<ctl name="IIR1 Band2" id ="1" value="0" />
<ctl name="IIR1 Band2" id ="2" value="0" />
<ctl name="IIR1 Band2" id ="3" value="0" />
<ctl name="IIR1 Band2" id ="4" value="0" />
<ctl name="IIR1 Band3" id ="0" value="268435456" />
<ctl name="IIR1 Band3" id ="1" value="0" />
<ctl name="IIR1 Band3" id ="2" value="0" />
<ctl name="IIR1 Band3" id ="3" value="0" />
<ctl name="IIR1 Band3" id ="4" value="0" />
<ctl name="IIR1 Band4" id ="0" value="268435456" />
<ctl name="IIR1 Band4" id ="1" value="0" />
<ctl name="IIR1 Band4" id ="2" value="0" />
<ctl name="IIR1 Band4" id ="3" value="0" />
<ctl name="IIR1 Band4" id ="4" value="0" />
<ctl name="IIR1 Band5" id ="0" value="268435456" />
<ctl name="IIR1 Band5" id ="1" value="0" />
<ctl name="IIR1 Band5" id ="2" value="0" />
<ctl name="IIR1 Band5" id ="3" value="0" />
<ctl name="IIR1 Band5" id ="4" value="0" />
<ctl name="IIR1 Enable Band1" value="1" />
<ctl name="IIR1 Enable Band2" value="1" />
<ctl name="IIR1 Enable Band3" value="1" />
<ctl name="IIR1 Enable Band4" value="1" />
<ctl name="IIR1 Enable Band5" value="1" />

<ctl name="RX1 MIX2 INP1" value="IIR1" />
<ctl name="RX2 MIX2 INP1" value="IIR1" />

<ctl name="SLIM_0_RX Channels" value="One" />
<ctl name="SLIM RX1 MUX" value="AIF1_PB" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
<ctl name="RX2 MIX1 INP1" value="RX1" />

[COLOR="Red"] <ctl name="IIR1 INP1 Volume" value="60" />[/COLOR]
<ctl name="HPHL Volume" value="20" />
<ctl name="HPHR Volume" value="20" />
<ctl name="RX1 Digital Volume" value="84" />
<ctl name="RX2 Digital Volume" value="84" />
</path>

You can adjust the level of the sidetone by adjusting the line marked in red, i.e. the mixer "IIR1 INP1 Volume". I currently have it set to 60 which I believe attenuates the microphone signal by 24 dB.

A higher number will feed back a louder copy of the microphone signal (in this context the auxiliary microphone by the headphone port) back to the headphones.

In the future I will be playing around with the IIR filter to minimize the effects of low frequencies that come in very annoyingly when using this setup while driving in a car (and possibly other noisy environments with significant low-frequency energy).

This mod should only get activated when the "voice-headphone" device is requested. Judging by the name I'm anticipating that this should only happen while making phone/video calls (cellular and VoIP).

Enabling sidetone for the handset use case

Sidetone is also absent in the handset use case. The lack of sidetone, though, is less obvious (but still useful) in this context.

Required mixer_paths.xml edits

If you want to enable sidetone in this context, replace

<path name="handset">
<ctl name="SLIM RX1 MUX" value="AIF1_PB" />
<ctl name="SLIM_0_RX Channels" value="One" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
<ctl name="CLASS_H_DSM MUX" value="DSM_HPHL_RX1" />
<ctl name="DAC1 Switch" value="1" />
</path>

with

<path name="handset">

<ctl name="CLASS_H_DSM MUX" value="DSM_HPHL_RX1" />
<ctl name="DAC1 Switch" value="1" />

<!-- the filter coefficients seem to be represented in Q28 format, i.e. 1.0 corresponds to 268435456 -->
<!-- this seems to be implementing cascaded direct-form I biquad IIR filters: -->
<!-- y[n] = b_0*x[n] + b_1*x[n-1] + b_2*x[x-2] - a_1*y[n-1] - a_2*y[n-2] -->
<ctl name="IIR1 Band1" id ="0" value="268435456" />
<ctl name="IIR1 Band1" id ="1" value="0" />
<ctl name="IIR1 Band1" id ="2" value="0" />
<ctl name="IIR1 Band1" id ="3" value="0" />
<ctl name="IIR1 Band1" id ="4" value="0" />
<ctl name="IIR1 Band2" id ="0" value="268435456" />
<ctl name="IIR1 Band2" id ="1" value="0" />
<ctl name="IIR1 Band2" id ="2" value="0" />
<ctl name="IIR1 Band2" id ="3" value="0" />
<ctl name="IIR1 Band2" id ="4" value="0" />
<ctl name="IIR1 Band3" id ="0" value="268435456" />
<ctl name="IIR1 Band3" id ="1" value="0" />
<ctl name="IIR1 Band3" id ="2" value="0" />
<ctl name="IIR1 Band3" id ="3" value="0" />
<ctl name="IIR1 Band3" id ="4" value="0" />
<ctl name="IIR1 Band4" id ="0" value="268435456" />
<ctl name="IIR1 Band4" id ="1" value="0" />
<ctl name="IIR1 Band4" id ="2" value="0" />
<ctl name="IIR1 Band4" id ="3" value="0" />
<ctl name="IIR1 Band4" id ="4" value="0" />
<ctl name="IIR1 Band5" id ="0" value="268435456" />
<ctl name="IIR1 Band5" id ="1" value="0" />
<ctl name="IIR1 Band5" id ="2" value="0" />
<ctl name="IIR1 Band5" id ="3" value="0" />
<ctl name="IIR1 Band5" id ="4" value="0" />
<ctl name="IIR1 Enable Band1" value="1" />
<ctl name="IIR1 Enable Band2" value="1" />
<ctl name="IIR1 Enable Band3" value="1" />
<ctl name="IIR1 Enable Band4" value="1" />
<ctl name="IIR1 Enable Band5" value="1" />
<ctl name="RX1 MIX2 INP1" value="IIR1" />

<ctl name="SLIM RX1 MUX" value="AIF1_PB" />
<ctl name="SLIM_0_RX Channels" value="One" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
[COLOR="red"] <ctl name="IIR1 INP1 Volume" value="72" />[/COLOR]
</path>

Again, you can adjust the sidetone gain by modifying the "IIR1 INP1 Volume" parameter. In this example, I have slightly increased the value compared to the headphone/headset case. One reason is that there is only one loudspeaker in this context, so there is more gain required to achieve the same effect.

Shy of having access to a telephony compliance lab, which measures sidetone levels in an anechoic environment with a phone mounted on an artificial head in accordance to international standards, there is no way for me to suggest a level. Just experiment a little and find a value that works for you. The best way to experiment would be to use tinymix with which the sidetone level can be adjusted during a call with

tinymix "IIR1 INP1 Volume" X

where X=[0,124].

NOTE: you may not want to use this mod if you are wearing a hearing aid as hearing aid compatibility (HAC) is not guaranteed, which could cause serious issues.

Edit: I expect this mod to work on all MSM8974 chipsets and WCD93*0 audio codec in combination with ROMs that still make use of the "voice-headphones" device, which is up to the audio HAL.

References

[1]Wikipedia's explanation of sidetone

[2]NPR story on sidetone

[3]Sony Experia Z1