[MOD] Codec-level Audio Mods for Pixel Devices: BiQuads, Stereo Capture and Playback

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
Attached is an installer for up to three hardware-level audio mods that I've created over the last few years.
Important: This installer is not flashable via TWRP, but needs to be installed using an adb root shell as outlined below.

The three mods that can be installed in any combination are
  1. The dual speaker playback mod as originally presented in this thread. When installing this mod, an app will also be installed that offers the following functionality:
    • when the screen is on, the main loudspeaker level is reduced significantly to bring down its volume to the one that is attainable with the earpiece speaker. The idea is that when the screen is on you may want to use it to watch a movie or play a game where the stereo effect may enhance the listening experience. This is a "personal" use-case where the lower overall volume may not be a huge problem
    • when the screen is off the main loudspeaker level is again raised to its maximum capability to not miss notifications and alarms, etc
    • There is an option offered to force maximum gain also in case the screen is on, for instance when sharing a YouTube video with friends or when using the speakers in the car in navigation mode
    The above functionality can be controlled with a new permanent notification with three buttons: "stereo", "mono", and "mode", which can be "adaptive" or "stock". If you install the dual speaker mod, an accompanying app/service will be installed that automatically shows the above referenced permanent notification. This "app" has no UI other than the permanent notification. It is really a service that automatically starts upon boot. Keep in mind that you will need to unlock the phone twice after the boot process has been completed for the service to become active. The reason for this is that Android only makes most services available only after the initial unlock as a security feature. After that the screen needs to turn off at least once for the speaker control service to detect the screen state. Also, this service requires root privileges to function properly.
  2. Stereo camcorder audio recording mod. Any app that uses the CAMCORDER device is now capable of recording stereo sound. Examples are Google's stock camcorder or "Easy Voice Recorder Pro".
  3. Headphone biquad filtering for frequency response compensation as first made available here. This option will also install the accompanying biQuads app and relevant files. REQUIREMENTS: system-less root and @flar2 's excellent ElementalX kernel starting with version 1.02, with codec power gating option disabled in the installer.

There are actually two installer provided:
  • chdloc_hardware_audio_mods_pixel__ull.tar.gz : retains ultra-low latency (ULL) audio playback, but only supports the main loudspeaker to be active in cases where ULL is being asked for
  • chdloc_hardware_audio_mods_pixel__no_ull_*.tar.gz: allows both loudspeakers to be active even when ULL is being asked for by an app. However, under the hood ULL is converted to low-latency playback only.
I was unable to get both loudspeakers to play simultaneously in ULL mode on a stock system/kernel. ULL seems to invoke very different data handling code inside the kernel (from IRQ-based to non-IRQ-based). It appears that two backends (SLIMBUS_0_RX and QUAT_MI2S_RX) cannot be simultaneously active in non-IRQ mode. It is possible that this "problem" can be fixed with a custom kernel, but I really don't want to go that route. That's why I opted to re-route the ULL plumbing to make use of the low-latency path instead. According to the AOSP source code (platform.c), ULL promises 7 ms of latency while low-latency promises 13 ms. Whether that delta makes a difference in day-to-day use, particularly in VR mode, I don't know (yet).



To install, download the attached archive to your PC and push it to /data/local/tmp on your Pixel
Code:
adb shell rm -rf /data/local/tmp/chdloc* && adb push chdloc_hardware_audio_mods_pixel*.tar.gz /data/local/tmp/
Then enter an adb shell and copy the following string of commands into a root shell:
Code:
cd /data/local/tmp && gzip -d chdloc_hardware_audio_mods_pixel__*.tar.gz && tar -xf chdloc_hardware_audio_mods_pixel*.tar && gzip chdloc_hardware_audio_mods_pixel*.tar && chmod -R a+rw chdloc* && cd chdloc_hardware_audio_mods_pixel && chmod 744 install_chdloc_mods.sh
to install type
Code:
./install_chdloc_mods.sh
and select your install option, which also includes "revert to stock".


The following hidden text shows the original OP for reference:

It has been a tradition in the Android community to enable the earpiece speaker for multimedia playback to somewhat mitigate the drawback of having only one bottom-firing loudspeaker. I have been running a "true stereo" mod on my Nexus 5 for almost two years with great success.

The Pixel is a little bit different. Like some other phones with the SD820/821 it uses a separate speaker DAC/amp, which makes this mod quite a bit more tricky. Let me get this out of the way: the bottom speaker gets *much* louder than, for instance, the one on the Nexus 5. You cannot expect the earpiece to get this loud to create any form of "surround" effect. The only way to get there is to lower the volume of the main loudspeaker. This is what I'm describing below. This work is in no way, shape or form complete. For now, I'm giving here an outline on what needs to be done to enable dual-loudspeaker playback. I encourage others to try it out and chime in. So here it goes:

First of all you need to be rooted. Then modify the following /system/etc/mixer_paths.xml {...}.
The installation process is now described here


Now you need to save the file and reboot your phone. When you play audio you will notice that the earpiece is barely audible against the main speaker. The only way around this is to lower the speaker gain. This can be done by writing to a register in the amplifier which sits on the i2c bus:
Code:
 echo 0xZZ0f > /sys/kernel/debug/tfa98xx-34/regs/06-AUDIO_CTR
where ZZ is the gain. By default, the speaker is set to 0 dB of gain with ZZ=00, i.e.
Code:
 echo 0x000f > /sys/kernel/debug/tfa98xx-34/regs/06-AUDIO_CTR
Now each "tick" in the upper eight bits in this 16-bit number lowers the gain by 0.5 dB. The last two gain settings are FE which is -127 dB and FF which mutes the speaker.

In my short tests I have found the a gain of -16 dB for the main speaker, i.e.
Code:
echo 0x210f > /sys/kernel/debug/tfa98xx-34/regs/06-AUDIO_CTR
and a gain of +6 dB for the earpiece (see above) gives fairly balanced left-right volume. The speaker volume could be adjusted via an app depending on the use-case or upon boot via a script in /su/su.d

Note that the mod at this stage is dual-mono only.

Going forward I'll try to enable true stereo or something like the HTC10 tweeter-woofer arrangement.
I understand that all of this appears fairly complicated, so work needs to go into making this actually useful for others with flashable zip and control app. Any volunteers...?

Updates
  • November 9: first release of a speaker control app
  • November 7: the no-sound on the earpiece speaker during an incoming call has been fixed. For details, refer to this post. Please test and report back
  • November 3: stereo support, the left channel is played by the earpiece and the right channel is played by the main speaker. Note the updated "speaker" device above. The line in red (QUAT ...) tells the mixer to send two channels to the speaker dac/amplifier. By default, the dac/amp mixes the two channels into a mono stream. If you want stereo, then issue
    Code:
    echo 0x8093 > /sys/kernel/debug/tfa98xx-34/regs/04-I2SREG # right channel only
    at any time on the command line or add to a script in /su/su.d so it gets applied on boot. If you want to go back to left+right on the main speaker then issue
    Code:
    echo 0x809b > /sys/kernel/debug/tfa98xx-34/regs/04-I2SREG # mono mix
    . With the above changes the earpiece always plays the left channel.
  • November 2: Initial revision

Known limitations
  • Speakerphone telephony resets the DAC/amp of the main speaker and the above modifications get wiped. Hence, it would be ideal to control this mod with Tasker or some other native app.
  • There currently is an issue with RX audio on the earpiece with an incoming phone call. There will be nothing coming out of the earpiece. Switching to speakerphone works fine. Outgoing calls are fine. This has to do with the above (necessary) changes to mixer_paths.xml and the timing on how audio devices are set up and torn down in specific use cases. An explanation and possible solutions are given below. fixed (?)

    So here is the problem: A call comes in and the system plays the ringtone using the "speaker" device. With the changes above, the speaker device now also activates the earpiece speaker by default. When you answer the call, the audio HAL switches the audio devices by activating the relevant capture and playback devices. The playback device is different from the "speaker" device, but it involves the earpiece unless the phone is connected to a (potentially bluetooth) headset. Unfortunately, the "speaker" device gets disabled last, which means that the earpiece gets disabled. Here is the sequence of events as caught by logcat:

    Phone is RINGING

    17:30:04.578 adev_set_mode: mode 1
    17:30:04.904 out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=2
    17:30:04.908 select_devices: changing use case low-latency-playback output device from(1: handset, acdb 7) to (2: speaker, acdb 15)
    17:30:04.908 enable_snd_device: snd_device(2: speaker) {=> chdloc: this line enables the earpiece}
    17:30:04.924 enable_audio_route: usecase(1) apply and update mixer path: low-latency-playback speaker

    Phone is answered in HANDSET mode

    17:30:11.020 adev_set_mode: mode 2
    17:30:11.123 out_set_parameters: enter: usecase(1: low-latency-playback) kvpairs: routing=1
    17:30:11.126 enable_snd_device: snd_device(19: voice-handset-tmus) {=> chdloc: this line enables the earpiece}
    17:30:11.128 enable_snd_device: snd_device(55: voice-dmic-ef-tmus)
    17:30:11.153 enable_audio_route: usecase(15) apply and update mixer path: voicemmode1-call
    17:30:11.220 select_devices: changing use case low-latency-playback output device from(2: speaker, acdb 15) to (19: voice-handset-tmus, acdb 88)
    17:30:11.220 disable_audio_route: usecase(1) reset and update mixer path: low-latency-playback speaker
    17:30:11.277 disable_snd_device: snd_device(2: speaker) {=> chdloc: this line disables the earpiece}
    17:30:11.304 enable_audio_route: usecase(1) apply and update mixer path: low-latency-playback
    17:30:14.058 disable_audio_route: usecase(1) reset and update mixer path: low-latency-playback

    I see three options to fix the issue:
    1. Have the earpiece constantly enabled. I'm currently testing this method to see whether there are any side effects. I would be in favor of this method if it works.
    2. Use Tasker to detect an incoming phone call and have Tasker enable the earpiece. This is actually very doable, but kludgy. I'd use this approach if the first one proves problematic.
    3. Mess with the audio HAL to disable the speaker *before* the voice-handset-*** device is enabled. As this involves source code changes and, therefore, a modified audio HAL (/system/lib/hw/audio.primary.msm8996.so), this would be my least favorite option.

 

Attachments

Last edited:

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
Update: Full stereo support added to the OP. Note that for best stereo imaging, the gain for the main speaker needs to be reduced significantly. Stereo media playback is likely only useful for personal media consumption or gaming in a relatively quiet environment. This mod lends itself nicely to Tasker (or native app) integration with which stereo can be enabled on-demand.

Next, I'll look into an HTC 10 like setup where the earpiece is used as a tweeter. The idea is that the earpiece (and by extension the main speaker) gain can be kept higher because distortions that are caused by high frequency clipping are less audible than the ones that result from low-frequency clipping.


Update: There currently is a problem with this implementation in that there is, initially, no audio coming out of the earpiece when *receiving* a phone call. You can force audio to come out of the earpiece by quickly toggling to and from speakerphone mode. Outgoing phone calls are fine. Please keep this in mind when trying the mod. I'm currently investigating the exact cause.

Update 2: I think I'm understanding the problem. See the OP for an explanation and possible solutions
 
Last edited:

treIII

Senior Member
Jul 10, 2012
3,175
581
0
I'm a bit lost. 1. Do I need to change everything from "this" to " with" as above for the mod to work and 2. Once necessary files are replaced do I just save and let root create the XML.bak file or does the file I create go in su etc? Thanks

Sent from my Pixel XL using XDA-Developers mobile app
 
Last edited:

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
So what you're saying is when answering a call, switch to loudspeaker then ear piece?
Yes, that is the current workaround. I'm currently testing additional mixer_path.xml mods that may address this issue.


I'm a bit lost. 1. Do I need to change everything from "this" to " with" as above for the mod to work and
Yes

2. Once necessary files are replaced do I just save and let root create the XML.bak file or does the file I create go in su etc? Thanks
Well, to stay in the spirit of system-less root, you don't want to modify /system. Instead, copy the modified mixer_paths.xml file to /su/etc
and create a file (bind mount) called 10mixer_paths in /su/su.d/
Code:
#!/su/bin/sush
mount -o bind /su/etc/mixer_paths.xml /system/etc/mixer_paths.xml
change the permissions to 700 (rwx------), and reboot.
 

treIII

Senior Member
Jul 10, 2012
3,175
581
0
Yes, that is the current workaround. I'm currently testing additional mixer_path.xml mods that may address this issue.



Yes


Well, to stay in the spirit of system-less root, you don't want to modify /system. Instead, copy the modified mixer_paths.xml file to /su/etc
and create a file (bind mount) called 10mixer_paths in /su/su.d/

change the permissions to 700 (rwx------), and reboot.
Does I need to make a file bind mount inside of su/su.d/ thanks
 

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
from what i read, the mod seems applicable on the OP3 as well, or is the S821 having a different hardware setup than the S820 ?
The main codec is identical, but they may have a different speaker DAC/amp. As root run the following two shell commands
Code:
ls /sys/module | grep snd_soc
and
Code:
find /sys -name '*AUDIO_CTR*'
and post the result.
 

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
Update: The procedure described below is outdated. See this post for the new method.


I think I found a way to fix the silent earpiece speaker when a call comes in. It requires additional mixer_paths edits. I have attached an archive with three files:
  1. mixer_paths.xml.stereo: copy (and rename!) to /su/etc/mixer_paths.xml; I dialed the earpiece gain back to 84 dB to get rid of distortions.
  2. 20speakerctrl: copy to /su/su.d and make executable (700, rwx------). This script is executed on boot and sets the speakers for stereo and lowers the level of the main speaker by around 18 dB.
  3. mixer_paths.xml.stock: this is the stock mixer_paths file; if you want to go back to stock behavior, copy this file to /su/etc/mixer_paths.xml and delete /su/su.d/20speakerctrl
Please test this setup and report back. Note that you can currently only modify the main speaker gain and have it "stick" with the 'echo' command as described in the OP. To play around with the earpiece volume while media is playing you can use the following command in a root shell
Code:
tinymix "RX0 Mix Digital Volume" X
where X={0,1,...,84,85,...,124}. The default is X=84 which applies 0 dB of gain. Each "tick" up or down changes the gain by 1 dB. Add gain very carefully. At maximum volume, I would highly advise not to go beyond 90. Note that changing the earpiece volume this way does not "stick" and it defaults back to 84 as soon as you change the media stream (skip, different app, etc). You will need to run a custom kernel with sound control to be able to fully control the volume of the earpiece speaker.

There is still the issue that a speakerphone call resets the main speaker's volume to default. Over the next couple of weeks, I'll come up with a Tasker app -- which means you do not need to have Tasker installed -- which initially
  • re-applies the currently chosen gains after a phone call
  • lets you quickly toggle between the low-volume stereo setup and the high-volume stock setup
Other things this app could do is go back to stock behavior when the screen is off, so you won't miss notifications and/or alarms due to the lower overall volume of the stereo mod.
 
Last edited:

Juzman

Senior Member
May 4, 2011
2,463
713
193
Townsville
justynsmith.info
There is still the issue that a speakerphone call resets the main speaker's volume to default.
So, after each call, we have to run the script in /su/su.d to reapply the volumes correctly? If that's the case, can always use Script Manager, and set a widget icon on home screen. After a call, tap the widget to execute the script again.
 
Last edited:

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
So, after each call, we have to run the script in /su/su.d to reapply the volumes correctly? If that's the case, can always use Script Manager, and set a widget icon on home screen. After a call, tap the widget to execute the script again.
Correct. The idea, though, is to eventually have this done automatically by a Tasker app.
 

Juzman

Senior Member
May 4, 2011
2,463
713
193
Townsville
justynsmith.info
Correct. The idea, though, is to eventually have this done automatically by a Tasker app.
Sweet as. Question two:
mixer_paths.xml.stock: this is the stock mixer_paths file; if you want to go back to stock behavior, copy this file to /su/etc/mixer_paths.xml and delete /su/su.d/20speakerctrl

Could we not just delete /su/etc/mixer_paths.xml instead? Since we will still have original in /etc/
 

chdloc

Senior Member
Jul 19, 2010
1,140
1,723
0
Sweet as. Question two:
mixer_paths.xml.stock: this is the stock mixer_paths file; if you want to go back to stock behavior, copy this file to /su/etc/mixer_paths.xml and delete /su/su.d/20speakerctrl

Could we not just delete /su/etc/mixer_paths.xml instead? Since we will still have original in /etc/
Sure, but then you probably also may want to delete the bind mount in /su/su.d as I'm not sure what would happen if the file the mount points to has been deleted.

In addition, there are a few more mods I'm going to release soon that some folks may want to play with (stereo camcorder recording and hardware audio filtering), so keeping that file around may come in handy.
 
  • Like
Reactions: Juzman