MusicPlayerDaemon / MPD

Music Player Daemon
https://www.musicpd.org/
GNU General Public License v2.0
2.11k stars 340 forks source link

Is bit-perfect playback possible on Android? #922

Closed kowalcj0 closed 3 years ago

kowalcj0 commented 3 years ago

Hi,

My current setup is:

and here's my mpd.conf on my mobile:

music_directory     "nfs://192.168.1.5/mnt/music/"

bind_to_address     "0.0.0.0"
port                "6600"

log_file         "/data/user/0/mpd/log"
state_file       "/data/user/0/mpd/state"

audio_output {
    type      "sles"
    name      "OpenSL ES"
    format    "96000:24:2"
}

database {
    plugin  "proxy"
    host    "192.168.1.5"
    port    "6600"
}

max_playlist_length         "524288"
max_command_list_size       "131072"
max_output_buffer_size      "131072"

Unfortunately format "96000:24:2" is ignored by MPD and when I listen to music on low volume I can hear a lot of distortions/hiss etc. When I use other music players (like Poweramp or USB Audio Player Pro) that support bit-perfect playback or up-sampling to lets say 24b 96kHz then all distortions and hiss are gone.

So, I was wondering if it's possible to somehow enable/force bit-perfect playback or up-sampling?

PS. I tried all 3 documented resamplers: soxr and libsamplerate are not supported on Adnroid and internal doesn't change anything

resampler {
  plugin "soxr"
  quality "very high"
}
MaxKellermann commented 3 years ago

Unfortunately format "96000:24:2" is ignored by MPD

How do you know that?

And how do you know the other programs support bit-perfect playback, and how do you know it's really bit-perfect?

You decided to delete the bug reporting template, and so you decided not to post the important details mentioned there. You make it hard for me to help you, and that's annoying!

So, I was wondering if it's possible to somehow enable/force bit-perfect playback or up-sampling?

No, it's impossible to enforce bit-perfect playback. Either your hardware and all driver layers between MPD and your hardware can do it or not. MPD can do its best, but if any layer can't do it, no software can possibly do that.

MPD will up-sample if the current audio format isn't supported, but a higher one is. This is the default, unless you tell it not to. So you don't need to "enable" it. You can only disable it.

But why did you configure format "96000:24:2"? This is one thing that can degrade quality.

kowalcj0 commented 3 years ago

Hi @MaxKellermann ,

Thank you for your prompt response!

Unfortunately format "96000:24:2" is ignored by MPD

How do you know that?

If MPD was outputting 96000:24:2 to my DAC, then an LED indicator it would lit up in Light Blue but at present it's constantly Blue, which means it's receiving 48kHz signal. Here's an excerpt from official manual https://www.audioquest.com/resource/1092/DragonFly-Cobalt-FlightManual-EN-07-19.pdf

Red: Standby
Green: 44.1kHz
Blue: 48kHz
Yellow: 88.2kHz
Light Blue: 96kHz
Purple: MQA

You decided to delete the bug reporting template, and so you decided not to post the important details mentioned there. You make it hard for me to help you, and that's annoying!

It was late at night when I created it, but AFAIR I din't open a Bug report but a Question. Can create a new one if you prefer it?

No, it's impossible to enforce bit-perfect playback. Either your hardware and all driver layers between MPD and your hardware can do it or not. MPD can do its best, but if any layer can't do it, no software can possibly do that.

Sorry for that, I confused bit-perfect playback with bit-perfect volume control which is supported by DragonFly Cobalt:

VOLUME CONTROL: 64-bit bit-perfect digital

There are many applications available (such as Roon, BitPerfect, Foobar, JRiver, Audirvana, Decibel, Amarra, etc.) that will automatically set the sample rate of DragonFly to that of the file, eliminating the need for manual setting of the sample rate.

MPD can do its best, but if any layer can't do it, no software can possibly do that.

I can't tell it for sure because I simply don't own a dedicated measuring equipment, thus the only option I'm left with is to have some trust in people behind lets say USB Audio Player Pro who say that they wrote a custom USB audio driver which bypasses the Android audio system completely -> https://www.extreamsd.com/index.php/products/usb-audio-player-pro

But why did you configure format "96000:24:2"? This is one thing that can degrade quality.

Because when I listen to music on my phone at low volumes on my fairly sensitive pair of IEMs which are plugged in to DragonFly Cobalt and its LED indicates that sample rate is 44.1 kHz or 48 kHz then I can hear a lot of distortions and hiss (not sure if I can call that noise floor). Those distortions are especially profound in quieter parts of a song. Although when I enable up-sampling to 24/96 in Poweramp or USB Audio Player Pro then all of those distortions are gone and the sound coming from my IEMs is super clean and simply dead silent in quieter parts of a song.

Hans Beekhuyzen explained few things on up-sampling in his videos: https://www.youtube.com/watch?v=h8X2QcRtWSI https://www.youtube.com/watch?v=r_wxRGiBoJg https://www.youtube.com/watch?v=X65ijUhqYxo

Thanks

MaxKellermann commented 3 years ago

If MPD was outputting 96000:24:2 to my DAC

That shows only what your DAC receives, but it doesn't show what MPD sends. You didn't post any data showing that. But in spite of not having any data, you claimed that MPD "ignored" your setting.

VOLUME CONTROL: 64-bit bit-perfect digital

This is an oxymoron. There is no 64 bit audio, and thus if you have something that processes 64 bit audio, it cannot possibly be bit-perfect. Digital volume control cannot be bit-perfect either, by its very basic definition. Don't be fooled.

they wrote a custom USB audio driver which bypasses the Android audio system completely

That app indeed uses libusb to bypass Android. MPD doesn't do that. So technically, it is possible that Android prevents bit-perfect playback on your setup, and that app solves the problem by bypassing Android. Use that app, and not MPD!

https://www.youtube.com/watch?v=r_wxRGiBoJg

Oh no, that video mentions MQA! No, I'm not interested in any videos about upsampling, even less so if I can clearly see it mentions this fraud called MQA.

kowalcj0 commented 3 years ago

Oh no, that video mentions MQA!

hahahaha Indeed! :) I agree with you that MQA is a fraud, but it doesn't mean that the rest of his reasoning can be immediately discarded. As it could sound a bit like a fallacy to me. Never mind.

That shows only what your DAC receives, but it doesn't show what MPD sends. You didn't post any data showing that. But in spite of not having any data, you claimed that MPD "ignored" your setting.

OK, I did a quick tests. I've added 3 flac files to a playlist:

then played them via phone's headphone socket and then using DragonFly USB DAC.

Here are excerpts from the attached log files: headphone-output.txt:

output: converting in=44100:16:2 -> f=44100:16:2 -> out=96000:16:2
...
output: converting in=88200:24:2 -> f=88200:24:2 -> out=96000:16:2
...
output: converting in=96000:24:2 -> f=96000:24:2 -> out=96000:16:2

usb_dac.txt:

output: converting in=44100:16:2 -> f=44100:16:2 -> out=96000:16:2
...
output: converting in=88200:24:2 -> f=88200:24:2 -> out=96000:16:2
...
output: converting in=96000:24:2 -> f=96000:24:2 -> out=96000:16:2

You're right, MPD isn't ignoring format "96000:24:2" setting! Sorry for imputing that. Although the output bit depth is always 16bit. Is there a way to change that?

Use that app, and not MPD!

:) I do use those apps but for "local" playback (for files stored on my internal phone storage). MPD has an amazing feature to play files straight from a NFS share, which both of those apps lack.

MaxKellermann commented 3 years ago

Although the output bit depth is always 16bit. Is there a way to change that?

Now that's a good hint. To this piece of MPD's source code:

https://github.com/MusicPlayerDaemon/MPD/blob/b04c6fbd7287fb7155a8a24852aa274b99dd1ac6/src/output/plugins/sles/SlesOutputPlugin.cxx#L295-L296

MaxKellermann commented 3 years ago

Unfortunately, Android supports only 8 bit, 16 bit and 32-bit float. No 24 or 32 bit PCM. The best approximation would be 32 bit float. That's better, but not bit-perfect.

kowalcj0 commented 3 years ago

Now that's a good hint. To this piece of MPD's source code:

Is this something that you or other contributors potentially interested in working on in the near or far future?

That app indeed uses libusb to bypass Android. MPD doesn't do that.

Ditto, are there any plans to add support for libusb?

The best approximation would be 32 bit float. That's better, but not bit-perfect.

What would happen if I changed S16 to audio_format.format = SampleFormat::S32; and rebuild the app?

MaxKellermann commented 3 years ago

Is this something that you or other contributors potentially interested in working on in the near or far future?

If there's interest, yes.

Ditto, are there any plans to add support for libusb?

No.

What would happen if I changed S16 to audio_format.format = SampleFormat::S32; and rebuild the app?

There's a little bit more to do for 32-bit float support, so you'd only hear a lot of loud noise.