HITMAnsOFT
Posts: 5
Joined: Sun Jan 15, 2017 10:05 am

DSD / 1-bit Sigma-delta sound driver

Sun Jan 15, 2017 10:44 am

Hi,

I have an idea of driving a stereo Class D output stage off the Raspberry Pi 2's GPIO pins, without analog filtering until just before the speakers. For that I'm using both channels of the PWM peripheral in serializer mode, clocked at PLLD/177 =~ 2824858 Hz, which is within 0.1% of the standard DSD64 sampling frequency of 2822400 Hz.

I've written two small test applications in C using bcm2835 library v1.51 from http://www.airspayce.com/mikem/bcm2835/ . I'll open a gitlab(or github) project shortly.

First app is demuxing and playing DSD64(SACD) sound files in .dsf format directly.

Second app is playing .wav/.flac files by running them through a 2nd order Sigma-Delta digital modulator with 64x upsampling to obtain the required ~2.8MHz sampling rate. The quality of conversion is not ideal, but I'm working on it (will need higher order to improve quantizer noise shaping).

These applications are CPU-intensive because DMA and VPU aren't used and the PWM FIFO is filled from the CPU.

In order to be usable, the code needs to be ported to a Linux driver to use DMA effectively, maybe with VPU acceleration for sigma-delta conversion part.

Can anyone recommend any resources about how to implement a simple playback-only ALSA driver (VPU acceleration included)?

I've found the codes to bcm2835 kernel driver, but it looks like just a glue logic to VPU firmware, which I didn't find sources to.

Regards,
Arthur

EDIT: I created a gitlab repository: https://gitlab.com/HITMAnsOFT/snd-bcm2835-dsd
Unfortunately, the .dsf player code was lost before the repo was created by my stupid mistake, but it's simple to reimplement. Basically all it was doing is parsing the headers, reshuffling data words and feeding the PWM FIFO, as the samples are already in correct format.

jdb
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2116
Joined: Thu Jul 11, 2013 2:37 pm

Re: DSD / 1-bit Sigma-delta sound driver

Wed Jan 18, 2017 10:58 pm

With a 2.8MHz sample rate, you'll find that you exceed the maximum input frequency of a class-D power stage. Most have a maximum frequency of <1MHz.

An advanced sound driver is available, currently experimental:

viewtopic.php?f=29&t=136445

tl;dr: with audio_pwm_mode=2 in config.txt, the PWM engine is driven at 781250Hz with a 7-bit output resolution. Second-order noise shaping is applied to the oversampled signal for a ~CD-quality noise floor. The oversampling is done by the VPU and it can handle fractional rate conversion.

Note that sigma-delta shaping is inherently hard to parallelise - it's feedback loop which means every next sample depends on the previous loop state. The scalar units in the VPU handle the sigma-delta/quantisation. Second order is nice because the loop coefficients are 2 and -1, easy to implement with single-cycle instructions.

There's no real reason why you can't just bung the (unfiltered) PWM signal from this scheme into a direct-drive class-D output stage. Some require differential inputs, but that's easily done by just adding a NOT gate to the inverted input.
Rockets are loud.
https://astro-pi.org

HITMAnsOFT
Posts: 5
Joined: Sun Jan 15, 2017 10:05 am

Re: DSD / 1-bit Sigma-delta sound driver

Thu Jan 19, 2017 7:05 am

Thanks for your reply, JDB.

I've seen the post you linked, but didn't try it on my current development system yet. 7bit at 781.25kHz sounds like a good resolution to me, it does make sense to feed it into the output stage. Have you measured the SNR? I'll take a look into the bunch of papers I've gathered while doing this for the theoretical SNR estimation that can be achieved with 2-stage 7-bit sigma-delta. I have keen interest in implementation details. Is the source available? What algorithm are you using for oversampling?

I chose 2.8MHz 1-bit format because it is used in SACDs and was heavily tested and proven to have better characteristics than CD audio, and for the possibility to play DSD files directly (you lose volume control, unfortunately).
In the current version in gitlab I implemented 5-stage 1-bit sigma-delta with zero-order hold oversampling using only integer operations. Can you please have a look and advise if it this scheme can be implemented in the VPU?

Another idea I have is to use the onboard sound output as a DSD-over-PCM DAC: http://dsd-guide.com/dop-open-standard
tl;dr the player software packs DSD bits into high-rate PCM frames and sends to ALSA (mpd, for example, supports this), then the DAC detects that this is a DoP stream from marker bits and streams the extracted bits at 2.8224MHz directly to the analog low-pass filter. This scheme is not computation-intensive, just simple bit-shuffling. What do you think about this?

Regards,
Arthur

jdb
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2116
Joined: Thu Jul 11, 2013 2:37 pm

Re: DSD / 1-bit Sigma-delta sound driver

Thu Jan 19, 2017 11:38 am

With the VPU scheme, the quantisation noise floor is easily -95dBFS but THD is approx. -45dB (0.5%) primarily because the PWM is trailing-edge modulation rather than pulse-centred. If the modulation frequency were higher, harmonic distortion would reduce.

Source isn't available as it's in the firmware. The resampling filters implement an approximation of this scheme : https://ccrma.stanford.edu/~jos/resample/resample.pdf
Of course, open implementations are available, have a look at libsamplerate : http://www.mega-nerd.com/SRC/download.html

The quantisation and noise shaping is performed pretty much the same as you have implemented, except in fixed-point with adds/shifts rather than any multiplies.

I strongly suggest using a sensible FIR filtering scheme for interpolation. Zero-order-hold is generally a terrible filter unless you're oversampling a signal that has a tiny bandwidth. Also, to reduce computational load, split the filtering into multiple stages - it's more efficient to cascade big filters at low bitrates with small filters at high bitrates than have a huge interpolation factor.

You might want to consider using the I2S peripheral for 1-bit output. It's basically a serialiser/deserialiser with fancy stuff added on top. There's also an existing Linux driver that wouldn't be too hard to hack into supporting straight DSD bitstream rates.
Rockets are loud.
https://astro-pi.org

HITMAnsOFT
Posts: 5
Joined: Sun Jan 15, 2017 10:05 am

Re: DSD / 1-bit Sigma-delta sound driver

Thu Jan 19, 2017 4:00 pm

Thank you for the review and good advice!. I tried using libresample with SINC_*, but it was very slow on the CPU (probably because it's floating-point), so I decided to increase modulator order to compensate for the bad filter. Now I am looking for a suitable all-in-one H-bridge IC or a good gate driver that is fit for 1MHz operation. Most class D audio ICs are unfortunately analog-input only.

EDIT: I researched the PCM/I2S peripheral, it has only one data output pin, therefore it isn't suitable for stereo DSD output. PWM, on the other hand, does the job well. I really liked the sound from DSD playback (except for rare clicks from FIFO underrun).

jdb
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2116
Joined: Thu Jul 11, 2013 2:37 pm

Re: DSD / 1-bit Sigma-delta sound driver

Mon Jan 23, 2017 9:16 pm

Regarding filtering CPU load -

There are alternatives out there that use NEON instructions to vectorise the resampling/filtering stages. libav has a library called libavresample that purportedly has NEON support. Generally, you can expect a significant speed increase when using the NEON FPUs.
Rockets are loud.
https://astro-pi.org

HITMAnsOFT
Posts: 5
Joined: Sun Jan 15, 2017 10:05 am

Re: DSD / 1-bit Sigma-delta sound driver

Tue Jan 24, 2017 7:05 am

Thanks for the info JDB, I'll have a look at libavresample.
I have another question regarding the experimental PWM firmware: is the output duty cycle (and hence, the minimum pulse width) limited, or is it full scale (0-127)? The alsamixer volume control goes to +4db, what does that mean in terms of the output duty cycle when the input PCM is a 0dB sine? The question came to me while looking at the STA508 output stage IC, which specifies a minimum pulse width of 150ns., corresponding to the minimum PWM output of 15 if I understand everything correctly.

jdb
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 2116
Joined: Thu Jul 11, 2013 2:37 pm

Re: DSD / 1-bit Sigma-delta sound driver

Tue Jan 24, 2017 12:03 pm

There are no constraints on output pulse width other than saturation of the output value to 0-127 in order to prevent wraps if the delayed error + input value exceeds the available output range.

+4dB in alsamixer corresponds to an approximate 0-127 output range. Note that at this level you will get clipping which will squash the performance of the noise shaping. If the 150ns minimum pulse width is a hard requirement, then you should set the mixer to 0dB (-4dBFS). This ensures that the output range + noise shaping fuzziness won't generate output codes of 15 or below (or 112 or above).
Rockets are loud.
https://astro-pi.org

HITMAnsOFT
Posts: 5
Joined: Sun Jan 15, 2017 10:05 am

Re: DSD / 1-bit Sigma-delta sound driver

Wed Jan 25, 2017 7:13 am

All right, that's pretty much what I thought. Thank you again for helpful information and advices!

Return to “Bare metal, Assembly language”