Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DSD on ARM is broken #469

Open
Wang-Yue opened this Issue Jan 27, 2019 · 23 comments

Comments

Projects
None yet
6 participants
@Wang-Yue
Copy link
Contributor

commented Jan 27, 2019

Hi, Max. I'm using MPD to play DSD (either DoP or Native). I run into an issue that with the same Linux kernel version, same MPD version, and same DSD capable DAC, the sound is very different when running MPD on my Raspberry Pi (arm based) and PC (x64 based). PCM is not affected.
On ARM the DAC has a constant rustle sound. There're various bit manipulations happens in processing DSD music, which leads me to question whether ARM and x64 would feed the same data to a DAC. Is there some way I can easily output the data stream into a file and compare between the two?

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

I made some progress and changed the alsa output code (both are based on 0.21.4 code):

diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx
index 8f32cf8d7..20f436ac2 100644
--- a/src/output/plugins/AlsaOutputPlugin.cxx
+++ b/src/output/plugins/AlsaOutputPlugin.cxx
@@ -866,6 +866,11 @@ AlsaOutput::Close() noexcept
 	delete[] silence;
 }
 
+#include <iostream>
+#include <fstream>
+using namespace std;
+ofstream myfile("example.bin", ios::out | ios::app | ios::binary); 
+
 size_t
 AlsaOutput::Play(const void *chunk, size_t size)
 {
@@ -890,8 +895,10 @@ AlsaOutput::Play(const void *chunk, size_t size)
 
 		size_t bytes_written = ring_buffer->push((const uint8_t *)e.data,
 							 e.size);
-		if (bytes_written > 0)
+		if (bytes_written > 0) {
+			myfile.write((const char *)e.data, bytes_written);
 			return pcm_export->CalcSourceSize(bytes_written);
+		}
 
 		/* now that the ring_buffer is full, we can activate
 		   the socket handlers to trigger the first

and run on the same audio file with dop. The output file differs. They are same from the beginning but after a few megabytes they start to differ a lot. Even their final size doesn't match. ARM file size is a little bit smaller than the x86 output.

-rw-r--r-- 1 yue yue 137953280 Jan 27 16:22 example.bin.x86
-rw-r--r-- 1 yue yue 137816832 Jan 27 16:35 example.bin.arm

that is so weird. @MaxKellermann any thoughts you can share?

Anyway the above proved that there is a bug on arm processors.

@Wang-Yue Wang-Yue changed the title Question: any way to stream dsd/dop file to a file? DSD on ARM is broken Jan 28, 2019

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

v0.20.23 works fine. things breaks after v0.21. Very likely an endianness bug in the alsa output.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Endianess? ARM is little-endian just like x86.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

My bad. But starting from v0.21 things are broken for ARM & DSD (either DoP or Native) only.
x86 and arm generate different buffer files when applying the patch above. Even their dump file size differ.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Did the ALSA plugin insert silence because not enough data was delivered? This is not logged - you could set a breakpoint in the plugin.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

I don't know --- I would say this is probably not the real cause.

The situation is, my pc plays dsd files nicely, while raspberry pi doesn't. If extra silence is causing issue, it should make raspberry pi dump file bigger. But in the above test, raspberry pi dump file is smaller than the pc one.

and I assume silence is something with a pattern (such as 0000). The place that starts to differ does not show that pattern.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Actually, 0x69 is the DSD silence pattern, see src/pcm/Traits.hxx.
Do MPD's unit tests succeed? MPD has one unit test for DoP export.
What would be really helpful is a git bisect, though I understand building MPD is extremely slow .... can you cross-compile or use distcc?

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

Umm.. I do see a lot of 0x69 there.

Could you let me know how to perform the DoP unit test?
I can let you know whether it succeed for v0.20.23 and v0.21 or not.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Configure with -Dtest=true and then run ninja test

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

ran out of memory a few times when building the test but I managed to get this done.

congratulations, it passes all tests

 1/13 TestUtil                                OK       0.10 s 
 2/13 TestRewindInputStream                   OK       0.10 s 
 3/13 test_mixramp                            OK       0.08 s 
 4/13 test_protocol                           OK       0.08 s 
 5/13 test_queue_priority                     OK       0.03 s 
 6/13 TestFs                                  OK       0.05 s 
 7/13 TestIcu                                 OK       0.09 s 
 8/13 test_translate_song                     OK       0.05 s 
 9/13 test_icy_parser                         OK       0.03 s 
10/13 test_archive                            OK       0.08 s 
11/13 test_archive_bzip2                      OK       1.79 s 
12/13 test_archive_zzip                       OK       1.78 s 
13/13 test_pcm                                OK       0.05 s 

OK:        13
FAIL:       0
SKIP:       0
TIMEOUT:    0

but clearly this only means the test does not cover everything.

As I said the two dump files started to differ after probably a megabyte (or a few hundred KB).
with a small fake sample you won't see it fail.

You can try by downloading the smallest dsd file on http://www.2l.no/hires/, for instance, http://www.lindberg.no/hires/test/2L-125_stereo-2822k-1b_04.dsf.zip , and then set the output to either DoP or native DSD. On Raspberry Pi this is broken to the point that you can hear the noise very clearly. The dump file size is different too.

This is not caused by a performance issue. MPD v0.20.23 on Raspberry Pi is capable of playing DSD256 without any issue (with a <10% low CPU utilization and sufficient USB trasport speed), , so it's pretty unlikely that the above DSD64 file would fail.

Even if you fill the period buffer with silence, it shouldn't affect the ring_buffer which is what I am copying above. ring_buffer should fill with exactly the same DSD data on both systems, but they are not right now.

@MusicPlayerDaemon MusicPlayerDaemon deleted a comment Jan 28, 2019

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Now that you've compiled the tests - please run test/run_decoder to run only the decoder plugin and see if its output differs.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

Compared the two files generated on PC and RPi. They are exactly the same.

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Jan 28, 2019

Sigh. That means it gets more complicated; the data gets altered somewhere later in the chain between decoder and output.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

Let me know what I can do to help if needed. I can apply patches and run tests on both machines if needed.

@coroner21

This comment has been minimized.

Copy link
Contributor

commented Jan 28, 2019

Hi @Wang-Yue, could you tell what sample format mpd using in your case on RPi for DSD native playback? I found that I have audible distortion on a beagle bone black when DSD_U32LE is used, however with DSD_U16LE everything works fine. So far I suspected this to be an issue with the ALSA sound driver but might as well be an mpd problem...

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Jan 28, 2019

@coroner21 , My DAC only supports DSD_U32 for native DSD. It's not an ALSA driver issue as mpd v0.20.23 has no problem playing that while 0.21 failed. The new alsa plugin also dump different data compared to the previous one. The issue happens on both DoP and Native.

@borine

This comment has been minimized.

Copy link
Contributor

commented Mar 7, 2019

@Wang-Yue - this is a long shot, but if you have time you could try an experimental fix I have for a different alsa device - it makes a slight change to the way mpd handles output to alsa devices. It's in a branch called alsa-revents in my mpd fork here:
https://github.com/borine/MPD/tree/alsa-revents
I don't have any DSD or DoP devices, so can't say whether this is likely to make any difference to your issue - i'm just curious to see if it helps.

@timpani2012

This comment has been minimized.

Copy link

commented Mar 10, 2019

@borine Dear borine, I used I2S of Raspberry Pi with ES9038Q2M DAC to test your mpd fork https://github.com/borine/MPD/tree/alsa-revents. The click sound of DSD still exists.
Very strange, for the Raspberry Pi, if you use a 64-bit OS instead of a 32-bit's, The version 0.21.x is no click sound.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Mar 11, 2019

@borine I will test in the coming week when I have access to the hardware

@timpani2012 it's not clicking. it's noise. clicking is another issue, see (raspberrypi/linux#2215). and the noise only happens on 0.21.x.

@Wang-Yue

This comment has been minimized.

Copy link
Contributor Author

commented Mar 12, 2019

@borine your patch doesn't work

@coroner21

This comment has been minimized.

Copy link
Contributor

commented Apr 13, 2019

Anyone working on this? As mentioned I found that when DSD_U32 is used the issue is there (distorted sound) whereas with DSD_U16 DSD playback is no problem at all. Any difference in the data being processed from input to output when the stream is split into 16bit chunks as opposed to 32bit?
This should give hopefully an idea how to address this problem (which I can work around by hard coding the DSD sample width to 16bit on my BBB-based DSD).

@MaxKellermann

This comment has been minimized.

Copy link
Member

commented Apr 18, 2019

No, nobody is working on this.

@franz159

This comment has been minimized.

Copy link

commented Apr 20, 2019

I noticed the issue with my Khadas Tone Board using Moode. least now I know the root cause, and continue using mpd 0.20.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.