Hi-Fi playback on Android (developers/testers only)

avs333

Senior Member
Apr 12, 2005
239
312
0
Each and every app on Google Play makes use of Android audio system to play music files (excluding my old andLess and the "USB Audio Recorder PRO" for external usb). The trouble with such playback is that you get a perfect 16/48000 or (44100) stream no matter the source file which is first downsampled then (digitally) clipped to the requested volume. Just try running this while playing _any_ file ("pcm15p" is for Qualcomm-based devices only, "15" needs be replaced with a different number for other ones):
Code:
adb shell cat /proc/asound/card0/pcm15p/sub0/hw_params
access: RW_INTERLEAVED
format: S16_LE
subformat: STD
channels: 2
rate: 48000 (48000/1)
period_size: 240
buffer_size: 480
As the time goes by and new devices receive better hardware, you'd expect this to change. No such luck with Android yet.
So I wrote a test app that plays lossless FLAC files directly through the ALSA driver.

The disgrace is:
1) It's targeted to recent msm8974 or apq8084 based devices and has no built-in support for other ones. If you've got an unsupported device, you have to modify the cards.xml file settings before anything, and this may be tricky (see below).
2) Root access is a must. A Permissive selinux setup may also be required (adb shell; setenforce Permissive).
3) No formats other than 16/24-bit FLAC or 16-bit APE are supported. There's a curious bug with 24-bit APE (won't be fixed);
-- All files not recognised for playback will be routed to Android;
-- If a particular sample rate (e.g., 176400) is not supported by hardware, it will be silently downsampled to its base rate (88200 or 44100 in this example);
-- If a particular format (i.e. a compressed stream, or 24-bit pcm or even 16-bit on some usb devices) is not supported, an error will be shown
4) In ALSA mode, volume controls work only when the app is in foreground (to be fixed);
5) Switching to/fro the Compr device may reboot your phone (kernel bug; workaround will be included later);

The settings file is called "/sdcard/.alsaplayer/cards.xml" and it's well commented. If you have a device missing there, all settings go in this file. A simple tip is checking the output of a mixer program like tinymixer and adding the diff when the device is playing and when it's not. These ALSA contrtols will be executed each time before the device is opened/closed/volume managed. The periods size/number to be added later.

This app also tries to play on "compressed" (a.k.a. "offload") Qualcomm devices, but you'll not be able to play FLAC files ulesss your kernel is patched; all newer msm8974/apq8084 devices support the hardware FLAC decoding, please ask your kernel developer to add the code like https://github.com/CyanogenMod/andr...mmit/f961d70994fe5f097b90e2cb5cfd87e90302c456 (I'm not providing a patch intentionally as (1) it's straightforward for an experienced developer (2) the codeaurora interface is really broken). For me, an offload FLAC playback sounds +worse+ than the direct pcm one (and I don't know the reasons why) -- I'm testing with the sennheiser IE-80 & audiotechnica ath 1000D headphones.

The program is opensource https://github.com/avs333/alsaplayer
The kudos go to skvalex who wrote almost all java part!
 

Attachments

Last edited:

ctheanh

Member
Aug 9, 2007
33
14
0
Dear @avs333,
So.. this alsaplayer is great.
I can config cards.xml to make it work with my Lenovo Vibe X3(that havs built-in Sarbe DAC es9018c2m). So It can work with 24 bits FLAC file in direct PCM mode( that can not work with other, even with Poweramp alpha in HI-RES Mode).
I just need to ask you for support.
+ Can you add support for WAV file?( I mean in alsa PCM mode)
+In offload mode, I know in my device it will use PCM divices number 9, with Control - MultiMedia 4. But it's hidden, I can config it in cards.xml but it il not show in devices list. Of course the pcm device 9 does not show when I tried to list it "alsa_aplay -L".
Thank you
 
  • Like
Reactions: avs333

avs333

Senior Member
Apr 12, 2005
239
312
0
Hi @ctheanh!

Thank you for the comments!
Playing WAVs is currently supported in offload mode only, due to some obscure bug with Java I'm failing to find. A good news is that @skvalex (who is much more experienced in Java) has recently decided to join the project, so it'd be fixed soon I believe. He's planning to make a decent interface for this app, which is very rudimentary for the time being (and I'm really sorry for that!).
As to the offload playback, the devices have to be called "/dev/snd/comprCXDY" to be detectable (you need to make a link to such names if they're called otherwise by your specific driver). alsa_play won't show them as they're not pcms.
 
Last edited:

ctheanh

Member
Aug 9, 2007
33
14
0
Hi @avs333
If you need tester, of course I am willing to join.
I am still optimize something with cards.xml to let it works smoothly. Still got some problem with volume( breaking my ear when changing from 24 bits to 16 bit). And the music will stop when receiving notification.
And, stupid question. How can I config to show offload device in device list?
 
  • Like
Reactions: Stallio

avs333

Senior Member
Apr 12, 2005
239
312
0
Hi @avs333
If you need tester, of course I am willing to join.
I am still optimize something with cards.xml to let it works smoothly. Still got some problem with volume( breaking my ear when changing from 24 bits to 16 bit). And the music will stop when receiving notification.
And, stupid question. How can I config to show offload device in device list?
You have to specify different volume ranges for 24-bit and for 16-bit/offload playback in cards.xml as the standard QC controls are a bit strange, to say the least. For digital controls, I'm using 0-84 for 16-bit pcms (or *any* offloads) and 40-124 for 24-bit pcms with reasonable defaults (please see the original cards.xml), but using analog controls looks more promising.
To avoid the conflicts with notifications, select a device that is not used for them as they may stop the device even if they fail opening it.
The devices (including offload ones) shown in the "Settings->Device name" list are those specified in "cards.xml" if it is present (to filter out irrelevant playback ones) , or +all+ playback devices otherwise. You can "cat /proc/asound/pcm" to find their ids (and names). E.g., use <device id="17" offload="1"> if you see "00-17: (Compress2) : : playback 1". Please let me know if this doesn't work for some reason.
 
  • Like
Reactions: LazerL0rd

LazerL0rd

Senior Member
Nov 2, 2016
1,301
1,007
123
Aberdeen, United Kingdom
www.thezest.dev
This seems very interesting.. I've been trying to get this working for AGES and have only successfully played 24 bit over Android O. ALSA is luckily very useful and I believe that card config can also be systemically implemented (as done in AINUR SAURON).

I'll happily join this project if you wish.
 
Last edited:
  • Like
Reactions: lordc

LazerL0rd

Senior Member
Nov 2, 2016
1,301
1,007
123
Aberdeen, United Kingdom
www.thezest.dev

LazerL0rd

Senior Member
Nov 2, 2016
1,301
1,007
123
Aberdeen, United Kingdom
www.thezest.dev
Any news?
On modern Android devices, I don't see why this is needed anymore. On older devices, if the kernel is set up correctly, this would work in theory as most devices allowed 24-bit PCM playback. Nowadays you got OpenSL ES HD, HiRes APIs from certain OEMs, HiRes paths for other OEMs, and probably stuff I missed out. In a post-Oreo world, I don't see why OEMs would have an excuse not to (or even custom ROM/kernel devs) unless the hardware has a limitation (unlikely).
 

tidusdacapo

Member
Nov 15, 2010
29
8
23
On modern Android devices, I don't see why this is needed anymore. On older devices, if the kernel is set up correctly, this would work in theory as most devices allowed 24-bit PCM playback. Nowadays you got OpenSL ES HD, HiRes APIs from certain OEMs, HiRes paths for other OEMs, and probably stuff I missed out. In a post-Oreo world, I don't see why OEMs would have an excuse not to (or even custom ROM/kernel devs) unless the hardware has a limitation (unlikely).
I agreed that the OEMS should have no excuses to set up the path correctly nowadays. However the fact is that, they DO NOT:(

I have lost the OpenSL ES HD since I updated my Samsung Galaxy S7 Edge to Oreo:silly:
 
  • Like
Reactions: LazerL0rd