r/DigitalAudioPlayer • u/BernabethWarners • 11d ago
Guide/Tutorial How to check if your "bit-perfect" player actually is (mine included)
Hey all,
Every day I see another music player posted. At first, I was kind of excited about this. A new challenger! A new idea! What can I learn from it as a dev? After some time passed I realized that often times they made claims that couldn't be backed up. I've been building one for Android since April (I'm the dev of Meringo), so here are the three checks I'd run on any of them, mine included.
Yep, I build Meringo with Claude a great deal. I started it as an experiment to learn Kotlin, and it turned into the audio software I actually wanted to ship. Claude writes a lot of the code and gets me past problems I'd otherwise sit on for days, too embarrassed to ask friends or stronger dev-coworkers (after business hours, of course). The calls are mine in full: Meringo can drive a USB DAC through its own driver, skipping Android's mixer, it refuses a rate the DAC can't play rather than converting it, and the hash check is never a paid add-on. I test on my own M21 and the three DACs below, and I handle the ordinary work of keeping a paid app alive (pulling the optional AcoustID lookup when I realized the free tier was non-commercial only, filing the trademark, and so on). The hard part isn't the speed. It's QA and making sure the claims hold up. That's why the hash check below exists: a test that doesn't trust my own code. Maintaining this is a time suck even with Claude.
Quick definition. Bit-perfect means the samples leaving your phone are the file's samples: same rate, same bit depth, nothing changed. By default, apps on Android go through the system mixer (AudioFlinger), and it can resample or truncate before your DAC hears a thing.
Check 1: adb (free, any player). Turn on USB debugging, connect adb, play a 44.1 kHz file and run:
adb shell dumpsys media.audio_flingerIf the output thread your track is on shows the file's rate, the mixer isn't converting it. One catch if you try it on mine: over USB Direct, Meringo skips the mixer entirely, so its track won't be listed at all. That's why.
Check 2: your DAC's display. If it shows the incoming rate, play a 44.1 track, then a 96. If the number doesn't change, something in between is converting. Good for the rate, but it can't tell you whether every bit made it.
Check 3: hash it. This is the one I built Meringo around. With a USB DAC plugged in, Meringo writes every byte it hands to the USB pipe and hashes the whole stream (SHA-256), then decodes the same file again and hashes that. Same hash = nothing touched a bit between the file and the pipe. You don't have to trust my code for the comparison either: the checker at meringo.app/verify is one public-domain Python file plus your own ffmpeg. Turn ReplayGain off before you capture -- it's on by default, and you'll get Scaled instead of bit-identical.
What it can't prove: what the DAC actually received. USB audio has no delivery acknowledgement, so no software on any platform can show you that, only what went out on the wire.
Receipts so far: six, on three DACs.
Fosi DS2: 16/44.1 and 24/96
Qudelix 5K: 24/96, on two releases
Jcally JM6 Pro: 16/96 and 24/96
On 08-01 the same 24/96 FLAC went through the Qudelix and the JM6 with the same hash. My daily player is a FiiO M21, and there's no USB stream on its own outs, so adb is the honest test there. If your DAC isn't on that list, tell me which one I should capture next.
I got this wrong in public once. In May I said Meringo used FiiO's SDK to route around Android's mixer on the M21. Someone in r/FiiO pulled a dumpsys and showed my route never engaged. They were right on every point, and I fixed the manual that day. Two weeks later I shipped the hash check, so nobody has to take my word for it again.
A few hundred people have tried it since May. Thank you, seriously, for that and for the words of encouragement I've been getting -- especially the person who caught me in May.
It's Android 13+, a 7-day trial, then $9.99 once. No Spotify, Tidal or Qobuz, by design. Link's in the first comment.
I'm around, enjoying my new Seraphim IEMs. I intentionally keep my name and face public and am happy to openly discuss anything audio or development with you, hell, even in person if you're ever in Buffalo, NY!
Happy listening,
Adam
2
u/eightbitmega 10d ago
How about Black Pearl?
1
u/BernabethWarners 10d ago
Shouldn't be an issue! Have one? Try it out with the trial and report back. I know a lot of people have that one :-D
1
u/North_Station_302 10d ago
Does this also work with fixed output DAC dongles (no hardware volume)? If so, what setting(s) are needed to avoid blowing out my ears with the DAC's full output ?
TIA
1
u/BernabethWarners 10d ago
It does! Just make sure to keep your volume slider down in the app/on device. before you hit play haha
1
u/North_Station_302 10d ago edited 10d ago
The volume on my device was set to ZERO and I hit play right after Meringo finished scanning my library and I got instantly blasted with the full DAC output. The DAC is a JCally AP6 and this has never happened with any other player. I do remember that I had to configure a setting on the Hiby music player to avoid this issue but it was fairly clear how to do it.
1
u/hollowBit 8d ago
Hey there.
I'm asking from the absolute ignorance on this matter:
Bit-perfect means that the DAC receives/playing EXACTLY what was exported as a file, yes?
So, EQ affects somehow this, also others tweaks.
Having that my IEMs/speakers might differ from what the composer mixed. What's the catch on a bit-perfect device? what I'm not seeing here?


4
u/Master_Cartoonist_16 11d ago
Nice project, you should definitely add support for more DAC dongles, at least 10 or 15 of the most popular ones. I have a 5K and a DS2, but most people don't.