• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

Introducing DSPi | A powerful, user friendly and open source DSP for less than a cup of coffee

When will the SPDIF input be released?
The SPDIF input branch is available now on the GitHub repository for anybody interested in building, testing or contributing. It is not yet production ready, so I recommend that non-developers wait until it reaches that point and a dedicated release is published.

The next release (v1.1.2) will include various useful enhancements to the existing feature set, along with several improvements to stability and robustness. Here is a non-exhaustive list of the upcoming changes:
  • Metering for all audio output channels
  • Peak metering for all channels
  • Improved CPU utilization metering, with a single user facing percentage indicator replacing the current per-core meters
  • New hybrid TPT SVF and single precision biquad filter architecture
  • 30% performance improvement and a 50dB reduction in low frequency noise floor
  • 10 configurable user presets
  • Improved Windows compatibility through USB descriptor and WCID updates to assign libusb-win32 drivers in place of WinUSB
 
Last edited:
The SPDIF input branch is available now on the GitHub repository for anybody interested in building, testing or contributing. It is not yet production ready, so I recommend that non-developers wait until it reaches that point and a dedicated release is published.

The next release (v1.1.2) will include various useful enhancements to the existing feature set, along with several improvements to stability and robustness. Here is a non-exhaustive list of the upcoming changes:
  • Metering for all audio output channels
  • Peak metering for all channels
  • Improved CPU utilization metering, with a single user facing percentage indicator replacing the current per-core meters
  • New hybrid TPT SVF and single precision biquad filter architecture
  • 30% performance improvement and a 50dB reduction in low frequency noise floor
  • 10 configurable user presets
  • Improved Windows compatibility through USB descriptor and WCID updates to assign libusb-win32 drivers in place of WinUSB
Please, don‘t forget the I2S output pins
 
Wow, how did you manage to improve it by that much? Sounds (heh) like magic
At the moment, the firmware makes use of TDFII biquads for all filters. This results in a somewhat elevated (though inaudible) noise floor for filters at frequencies below about Fs/10. The new architecture makes use of State Variable Filters below Fs/10 and standard 32-bit float biquads above. This results in each filter type being deployed within its optimal frequency band, with both filter types being more efficient that those currently in use.

I have been working with another developer who has very graciously donated some of his time to this project, which has enabled me to focus on some of the more user-facing issues for the next release.
 
Well my implementation is up, running, making music, and dramatically improving the frequency response of my DIY desktop system. Crazy what a few dollars buys these days. Thanks to Herr Dr. Weeb Labs once again! I’ll be contributing once I track down how that’s accomplished.

Few
 
This may be an unpopular perspective but I have never seen the practical need for exceptionally performant DACs (SINAD >80dB) so long as they are limited by distortion rather than noise.

In principle, I always want to achieve the best possible performance. This informs both my purchase and engineering decisions but to my knowledge, there has yet to be a DBT study demonstrating the practical need for distortion performance below -70dB.
I would argue for better than 100 dB SINAD as:
  1. As Amir pointed out in his explanations - it is good to have 10dB better performance on the upstream device before signal hits the amplifier that is likely to have SINAD close to 80 dB. That would raise the DAC target to about 90 dB.
  2. The main reason is - world is both far from perfect and flexibility is awesome - in the real setup you may have poor gain matching because gains on DACs and amplifiers might be fixed or you simply want to have a lot of headroom left to boost quiet recordings or add bass-boost. So you can easily loose another 10+ dB for that. Raising the DAC target to 100 dB.
  3. and finally - because it is 2026 and 100 dB is cheap and easy - look at the USB-C dongles that can do 100dB, why would you settle for anything less? :)
So I personally avoid DACs with less than 100 dB SINAD based on the principles above, but I agree that if you have to, DACs with 90 dB SINAD are not a tragedy and you can squeeze your standards even lower, but why? :)
 
  • Like
Reactions: MCH
Excellent project. I was looking around at pico spdif libraries, wondering how long it would take to code a simple device with spdif in/out and a few biquads in between, when I discovered some one has done all of the work for me.
I'm a Linux user so I am looking forward to the CLI control app. After a bit of fighting with the drivers I got the pico and console working in a windows VM. Seems to work as advertised, Great.
Feature Request:
To be useful as a active crossover, control over the Highpass / Lowpass filter Q is required so Linkwitz–Riley or higher order filter sections can be configured. Ideally the console app could handle setting up 4th and higher order filters, but just control of the Q would be great.
A first order low/high pass can be useful for speaker / room correction.
A Bass/Treble control would also be a good addition. This can be accomplished with one biquad. See https://wiki.analog.com/resources/tools-software/sigmastudio/toolbox/filters/generaleq2ndorder for the calculation of the coefficients.

It might be a bit redundant with I2S output on the roadmap but it's worth noting the cheap es9018 modules can accept spdif directly from the pico, it does not need to be one advertised as the spdif version. Just connect BCLK to the pico spdif pin and it just works. This is the module I am using.
es9018k2m.webp
 
I was eyeing similar boards yesterday. A ready-made version looks attractive. However, there seems to be only one dual op amp on the board (assuming the chip near the caps is a voltage regulator), so the ES9018 seems to operate in voltage mode. Again assuming it is a voltage regulator, those caps seem to be buffer caps, so the DC blocking cap on the outputs may be an undersized or even worse, a high-K ceramic cap.

All boards I looked at had the 74HC04 not populated unlike the one in your picture. What you describe, just using the BCLK in as SPDIF sounds strange. Maybe it works only on those boards?

The description on those boards without HC04 seems lost in translation. In the first paragraph it sounds like you have to buy the correct version, then the next seems to say you can select, possibly by changing a solder bridge:
1772363585379.png
 
It will be on GPIO 11 by default and will be assignable. I will be pushing the relevant commits to a new SPDIF input branch while I sort out the clocking complexities.

EDIT: The refactor branch has now been merged to main and I have updated the naming scheme within the project structure.

I have decided to expand the existing pin assignment functionality to encompass much more than just audio pins. Volume controls, tone controls, state toggles for functions (loudness compensation, crossfeed), channel mute toggles, channel gains, delays, three channel stereo (we'll talk about this one later) and more.

A standardized I2C interface for offloading external control and UI (LVGL) to dedicated MCUs such as ESP32-S3 and similar.
Will there be a way to load a few commands in the UI for the Zero to write to the DAC on startup for those DACs that don't have a hardware mode?
 
I was eyeing similar boards yesterday. A ready-made version looks attractive. However, there seems to be only one dual op amp on the board (assuming the chip near the caps is a voltage regulator), so the ES9018 seems to operate in voltage mode. Again assuming it is a voltage regulator, those caps seem to be buffer caps, so the DC blocking cap on the outputs may be an undersized or even worse, a high-K ceramic cap.

All boards I looked at had the 74HC04 not populated unlike the one in your picture. What you describe, just using the BCLK in as SPDIF sounds strange. Maybe it works only on those boards?

The description on those boards without HC04 seems lost in translation. In the first paragraph it sounds like you have to buy the correct version, then the next seems to say you can select, possibly by changing a solder bridge:
View attachment 514600
I should have looked a bit closer at the photo i posted. My board does not have the HC04 either.

The other IC is a 7660 for negative voltage generation. All the electrolytics are power supply caps. There is no output capacitor, the dc offset is 15mV or so.
The output opamp is setup with 820R to ground on the positive input and 820R between output and the negative input, combined with the 800R output impedance of the es9018 it makes the classic diff amp. Impedance is only balanced for common mode signals. Rejecting noise is probably more important than giving zero impedance to the 9018 outputs.
At this price point I wouldn't worry about it, it will sound good enough.

SPDIF in on BCLK is default behavior for es9018 (9038 as well I think) unless it is configured differently via the usually unused i2c interface.
The es9018 will autodetect spdif/i2s so this should work on just about any board. The HC04 on this board when fitted seems to just be a amplifier / buffer for a low level spdif signal.
 
Last edited:
Thanks. Where did you find that bit about the 800 R output impedance? I have scrolled up and down and except the statement on the first page that the outputs can operate in current or voltage mode, I couldn't find anything.

I would imagine that if in current mode, i.e. operating into virtual ground, an 800 R series resistance is not desirable.
 
Thanks. Where did you find that bit about the 800 R output impedance? I have scrolled up and down and except the statement on the first page that the outputs can operate in current or voltage mode, I couldn't find anything.

I would imagine that if in current mode, i.e. operating into virtual ground, an 800 R series resistance is not desirable.
It's on page 31 of the datasheet. "Note 1:
Differential (+ or –) current output is equivalent to a differential (+ or –) voltage source in series with an 806 +/- 11%
resistor. The differential (+ or –) voltage source has a peak-to-peak output range of 0.924 x AVCC = 3.05V and an
output offset of AVCC / 2 = 1.65V."

So the DAC is voltage output and there is nothing wrong with using it this way. It just works a little better with the reduced output voltage in current mode.
 
Quick update.

Spent most of today chasing a hum on the sub when using the PDM output. It was always there when music stopped. During playback it was masked. If I shorted the PDM pins, silence, so the sub itself was fine.

Running the sub in LFE mode was worst, as it bypasses the internal filtering and relies fully on the external filter board. Using the normal line input was better because it goes through the sub’s own LPF but manual crossovers.

I built a few revised filter boards and improved it each time, but the idle hum never fully disappeared. In the end I decided to drop PDM for the sub. I was going to invest in USB isolation filter but decided to go with an old DAC instead.

New setup for my enclosure build:

Coax SPDIF > cheap mini Neoteck DAC (with bonus extra sub channel for future proofing) > sub
Much cleaner solution and removes the analogue filter sensitivity.

Toslink > SMSL M6 Mini (dead screen but working and line out locked) > mains

Also noticed:
SPDIF output names revert after DSPi Console restart.
Getting at least 1 underrun on Spdif per song, but I cannot hear any artefacts.
On the positive side, I managed to import all my PEQs via text files without issue. Gave GPT an example of the DSPI filter txt export and dumped my Peace APO EQ's. Overall still very pleased with how this is turning out. Love the dynamic loudness compensation!

Only thing left for me is the rotary encoder implementation with push button source select.



20260301_163723.jpg
 

Attachments

  • DSPI With PEQ.PNG
    DSPI With PEQ.PNG
    184.1 KB · Views: 75
Last edited:
Please, don‘t forget the I2S output pins

Excellent project. I was looking around at pico spdif libraries, wondering how long it would take to code a simple device with spdif in/out and a few biquads in between, when I discovered some one has done all of the work for me.
I'm a Linux user so I am looking forward to the CLI control app. After a bit of fighting with the drivers I got the pico and console working in a windows VM. Seems to work as advertised, Great.
Feature Request:
To be useful as a active crossover, control over the Highpass / Lowpass filter Q is required so Linkwitz–Riley or higher order filter sections can be configured. Ideally the console app could handle setting up 4th and higher order filters, but just control of the Q would be great.
A first order low/high pass can be useful for speaker / room correction.
A Bass/Treble control would also be a good addition. This can be accomplished with one biquad. See https://wiki.analog.com/resources/tools-software/sigmastudio/toolbox/filters/generaleq2ndorder for the calculation of the coefficients.

It might be a bit redundant with I2S output on the roadmap but it's worth noting the cheap es9018 modules can accept spdif directly from the pico, it does not need to be one advertised as the spdif version. Just connect BCLK to the pico spdif pin and it just works. This is the module I am using.View attachment 514592
I’m glad that you’re enjoying the project! The terminal application will soon be available.

Regarding steeper filters, you can simply stack two high/low pass filters to produce a higher order filter. This is why there currently isn’t an explicit order setting. I may update this behaviour on the host side to make things clearer.
 
Quick update.

Spent most of today chasing a hum on the sub when using the PDM output. It was always there when music stopped. During playback it was masked. If I shorted the PDM pins, silence, so the sub itself was fine.

Running the sub in LFE mode was worst, as it bypasses the internal filtering and relies fully on the external filter board. Using the normal line input was better because it goes through the sub’s own LPF but manual crossovers.

I built a few revised filter boards and improved it each time, but the idle hum never fully disappeared. In the end I decided to drop PDM for the sub. I was going to invest in USB isolation filter but decided to go with an old DAC instead.

New setup for my enclosure build:

Coax SPDIF > cheap mini Neoteck DAC (with bonus extra sub channel for future proofing) > sub
Much cleaner solution and removes the analogue filter sensitivity.

Toslink > SMSL M6 Mini (dead screen but working and line out locked) > mains

Also noticed:
SPDIF output names revert after DSPi Console restart.
Getting at least 1 underrun per song, but I cannot hear any artefacts.
On the positive side, I managed to import all my PEQs via text files without issue. Gave GPT an example of the DSPI filter txt export and dumped my Peace APO EQ's. Overall still very pleased with how this is turning out. Love the dynamic loudness compensation!

Only thing left for me is the rotary encoder implementation with push button source select.



View attachment 514658
Thank you for the bug report. I will sort out the channel name issue.

Regarding the under runs, it is expected behaviour for the counter to increment when audio playback stops and starts between tracks. So long as it isn’t incrementing in the middle of a track, there’s no problem.

DSPi Console should also be able to import APO formatted text files.
 
Last edited:
Regarding steeper filters, you can simply stack two high/low pass filters to produce a higher order filter.
Yes, but you can't get the correct shape without a way of setting the Q. Some examples: An LR2 filter is composed of two cascaded 1st-order filters, or equivalently a 2nd-order filter with Q=0.5. An LR6 filter can be constructed from three cascaded 2nd-order sections with Q-values of 0.5, 1, and 1. A 5th-order Butterworth filter requires Q-values of (sqrt(5)-1)/2 and (sqrt(5)+1)/2, plus a 1st-order section.

A wizard to set the Q-values for arbitrary-order LR and/or BW filters would be nice for user friendliness. The general formula for Butterworth filters is simple: Q_i=1/(2*sin((N//2-i-0.5)*pi/N)), where i is the biquad index (0 to N//2-1), N is the filter order, and '//' is integer division. LR filters are just two cascaded BW filters of order N/2. Note that LR filters composed of odd-order BW filters require the polarity of one output to be inverted (usually the highpass one).
 
So, I have learned that the channel naming persistence bug affects only DSPi Console for Windows. The macOS version correctly persists channel names.

In addition, I may raise the base clock of the RP2350 to 307.2MHz when implementing user-configurable clocks and voltages. This new base clock would result in a performance improvement of about 7% without requiring a voltage increase from the stock 1.10V. All available user selections will result in integer dividers for both I2S and SPDIF output.

Yes, but you can't get the correct shape without a way of setting the Q. Some examples: An LR2 filter is composed of two cascaded 1st-order filters, or equivalently a 2nd-order filter with Q=0.5. An LR6 filter can be constructed from three cascaded 2nd-order sections with Q-values of 0.5, 1, and 1. A 5th-order Butterworth filter requires Q-values of (sqrt(5)-1)/2 and (sqrt(5)+1)/2, plus a 1st-order section.

A wizard to set the Q-values for arbitrary-order LR and/or BW filters would be nice for user friendliness. The general formula for Butterworth filters is simple: Q_i=1/(2*sin((N//2-i-0.5)*pi/N)), where i is the biquad index (0 to N//2-1), N is the filter order, and '//' is integer division. LR filters are just two cascaded BW filters of order N/2. Note that LR filters composed of odd-order BW filters require the polarity of one output to be inverted (usually the highpass one).
Q is configurable for LP/HP but is not currently exposed in Console, so I can certainly enable it. I will likely implement some additional logic which allow the user to set the filter order while managing cascades in the background.
 
Yes, but you can't get the correct shape without a way of setting the Q. Some examples: An LR2 filter is composed of two cascaded 1st-order filters, or equivalently a 2nd-order filter with Q=0.5. An LR6 filter can be constructed from three cascaded 2nd-order sections with Q-values of 0.5, 1, and 1. A 5th-order Butterworth filter requires Q-values of (sqrt(5)-1)/2 and (sqrt(5)+1)/2, plus a 1st-order section.

A wizard to set the Q-values for arbitrary-order LR and/or BW filters would be nice for user friendliness. The general formula for Butterworth filters is simple: Q_i=1/(2*sin((N//2-i-0.5)*pi/N)), where i is the biquad index (0 to N//2-1), N is the filter order, and '//' is integer division. LR filters are just two cascaded BW filters of order N/2. Note that LR filters composed of odd-order BW filters require the polarity of one output to be inverted (usually the highpass one).
Is LR4, arguably the most useful XO filter, impossible right now?
 
Is LR4, arguably the most useful XO filter, impossible right now?
LR4 is two 2nd-order Butterworth filters, which have a Q of sqrt(0.5) = 0.7071. This is the default Q, so LR4 seems to be the only Linkwitz-Riley filter you can implement currently ;).
 
In addition, I may raise the base clock of the RP2350 to 307.2MHz when implementing user-configurable clocks and voltages. This new base clock would result in a performance improvement of about 7% without requiring a voltage increase from the stock 1.10V. All available user selections will result in integer dividers for both I2S and SPDIF output.
Interesting. I will probably use this to decrease the clocks back towards the stock speed. I am running a crossfeed and a four filter headphone equalization, so I am using about 10% of the CPU which would be perfectly fine around 150 mhz.
 
Back
Top Bottom