• 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!

Enginerding with Weeb Labs

Do you still have the graphs for these measurements, the images seem to be down for me :)
I certainly do! Some of them, at least. Here you go.

1752612337113.png


1752612354889.png


1752612384229.png
 
I have finally found the time to write an iOS application that has been on my mind for a few years. The idea is to allow the user to generate reasonably useful speaker and headphone correction PEQ filters using only their ears. It is called uEQ.

The application generates a sine wave with continuously adjustable frequency and provides an on-screen touchpad with gain on one axis and Q on the other. The user sweeps the frequency until they find a significant dip or peak in their speaker or headphone response and then uses the touchpad to correct it. Once the user interacts with the touchpad, a PEQ filter is created at the current frequency and applied in real time to the sine. The user can then sweep the sine frequency back and forth while the filter frequency remains fixed, adjusting gain and Q until the peak or dip is eliminated. Each axis of the touchpad can be locked for greater precision.

Once the peak or dip is eliminated, the filter can be saved and the user moves on to the next one. There's an A/B bypass function, as well as pink noise mode to make before and after comparisons. A graph of the system's approximate response is calculated using inverse sine as filters are added. Once complete, the full set of filters can be saved as a named session and viewed, edited or exported to various common formats. Filters locations are indicated on the frequency slider, with red and blue colors indicating negative and positive gain respectively.

The Session view provides an expandable list of all previously generated filter sets, along with the same color coding to improve readability at a glance.

Lots of optional, more sophisticated information can be toggled in the settings.

This application is in the earliest stages of development and will no doubt gain a great deal of additional functionality as it progresses. At the moment, it only handles peaking filters but I want to implement high shelf, low shelf, high pass and low pass capability. A user-friendly, modern interface is of critical importance to me.



1756313772020.png
1756313784941.png
1756313805539.png
 
Further development progress. I have comprehensively overhauled the audio engine for more efficient slot and filter management, which has eliminated many bugs.

The "Measure" page has been redesigned with more carefully considered and responsive controls. Existing filters can now be selected and edited directly on the graph or via the new Filters list, which also serves to keep track of the remaining slots. Filters can be individually removed. Sine/Pink Noise selection has been migrated to a singular two-state control.

I have added a "Test" page, from which users can play local audio files directly through the filters that they have designed while modifying them in real time, complete with A/B fuctionality. This page requires a great deal of optimisation (both UI and engine) but is fully functional.

The "Export" page is next on my overhaul list but correctly exports to a generic format and provides channel-specific categories.

The next major components to implement are going to be automatic preamp gain calculation and filter type selection.

framed-Simulator Screenshot - iPhone 16 Pro - 2025-09-14 at 21.15.19.png
framed-Simulator Screenshot - iPhone 16 Pro - 2025-09-14 at 21.22.13.png
framed-Simulator Screenshot - iPhone 16 Pro - 2025-09-14 at 21.18.29.png
framed-Simulator Screenshot - iPhone 16 Pro - 2025-09-14 at 21.21.50.png
 
Last edited:
  • Like
Reactions: MCH
I am finally ready to call the schematic complete. I had considered the LMK1C110X but decided that I wanted to stick with parts readily available from LCSC to streamline the workflow somewhat. Only the V1402 needs to be acquired independently (and I already have a stock of those).

This was originally intended to be bus powered but I ultimately decided to use a standard 12V input.

View attachment 454639

Time to route.
I am not trying to be frustrating.
I have been scouring the web for something that can convert adat to aes3 and vice versa without all of the features of a full fledged "digital format converter"
I came across this thread as I've learned that AES3 and SPDIF are similar but not identical which is why I am interested in this project.
Certainly my engineering expertise is not enough to design something like this, or make a variation on your design, but I am curious if it would be nontrivial to do this more variably?
By that I mean, take a number of spdif connections and mux appropriately in adat or take a muxed adat connection and spit out that many spdif connections?
I suppose worth noting is that I understand changing the resolution is not just an easy tast, I suppose maybe through dip switches this could be predetermined?

My apologies if this isn't appropriate or if it is just a question you are uninterested in answering.
 
I am not trying to be frustrating.
I have been scouring the web for something that can convert adat to aes3 and vice versa without all of the features of a full fledged "digital format converter"
I came across this thread as I've learned that AES3 and SPDIF are similar but not identical which is why I am interested in this project.
Certainly my engineering expertise is not enough to design something like this, or make a variation on your design, but I am curious if it would be nontrivial to do this more variably?
By that I mean, take a number of spdif connections and mux appropriately in adat or take a muxed adat connection and spit out that many spdif connections?
I suppose worth noting is that I understand changing the resolution is not just an easy tast, I suppose maybe through dip switches this could be predetermined?

My apologies if this isn't appropriate or if it is just a question you are uninterested in answering.
any chance the Canare adapters at the bottom of this thread would solve your problem?
https://www.audiosciencereview.com/forum/index.php?threads/aliexpress-spdif-to-aes-converter.61142/

AES3<->S/PDIF coax is in many cases just an electrical conversion (impedance and sometimes voltage) as the signals are generally inter-compatible. I don’t know really anything about ADAT though.
 
any chance the Canare adapters at the bottom of this thread would solve your problem?
https://www.audiosciencereview.com/forum/index.php?threads/aliexpress-spdif-to-aes-converter.61142/

AES3<->S/PDIF coax is in many cases just an electrical conversion (impedance and sometimes voltage) as the signals are generally inter-compatible. I don’t know really anything about ADAT though.
Definitely super useful, and not outside of the scope of what I'm trying to do.
Ultimately I'm hoping to make use of some unloved but still extremely functional firewire audio interfaces after I get my DAD AX64.
I know that their analog i/o cards are excellent, but it is hard for me to feel like it is cost effective at the moment, and certainly a hard pill to swallow after spending that on an interface.
The AES3 cards have almost 4x the i/o for a similar cost as the analog ones, so I'm trying to do some creative problem solving in terms of affordable but good i/o for this rig.

The M-Audio ProFire 2626 can out put 4x4 adat smux/4 and 2 x 2 spdif at 192khz for oversampling, has decent, mic preamps, and is under 100$ so it seemed like it might be an excellent way to maximize my i/o without spending thousands more right off the bat.
 
Last edited:
I am not trying to be frustrating.
I have been scouring the web for something that can convert adat to aes3 and vice versa without all of the features of a full fledged "digital format converter"
I came across this thread as I've learned that AES3 and SPDIF are similar but not identical which is why I am interested in this project.
Certainly my engineering expertise is not enough to design something like this, or make a variation on your design, but I am curious if it would be nontrivial to do this more variably?
By that I mean, take a number of spdif connections and mux appropriately in adat or take a muxed adat connection and spit out that many spdif connections?
I suppose worth noting is that I understand changing the resolution is not just an easy tast, I suppose maybe through dip switches this could be predetermined?

My apologies if this isn't appropriate or if it is just a question you are uninterested in answering.
Maybe see if anyone's done it with a Pi Pico? S/PDIF send and receive has certainly been done using its PIO, so ADAT doesn't seem out of the question. AES3 would be a minor change to the S/PDIF code if it's not already done. The trickier part for AES3 in an ADAT out would be if you need to ASRC the incoming channels to sync the clock for the output, rather than assuming they're all sharing a clock - as I understand it the shared clock is a requirement for the multiple S/PDIF inputs on the Okto so it's not an unprecedented limitation.
 
I am finally ready to call the schematic complete. I had considered the LMK1C110X but decided that I wanted to stick with parts readily available from LCSC to streamline the workflow somewhat. Only the V1402 needs to be acquired independently (and I already have a stock of those).

This was originally intended to be bus powered but I ultimately decided to use a standard 12V input.

View attachment 454639

Time to route.
"Prism, which takes an 8-channel 48KHz ADAT input (from an audio interface or otherwise) and outputs four (4x2ch) SPDIFs"

@Weeb Labs - how did it go with your super-useful ADAT to SPDIF converter? It is crazy that such basic product does not exist already, but that only makes your design so much more valuable :)

The only reasonable option to convert ADAT to consumer 2ch digital on the market today is RME Digiface USB - which is a wonderful device, but about 4x more expensive and overpowered than it should be if all you need is to split ADAT into 4x stereo DAC outputs :)
 
"Prism, which takes an 8-channel 48KHz ADAT input (from an audio interface or otherwise) and outputs four (4x2ch) SPDIFs"

@Weeb Labs - how did it go with your super-useful ADAT to SPDIF converter? It is crazy that such basic product does not exist already, but that only makes your design so much more valuable :)

The only reasonable option to convert ADAT to consumer 2ch digital on the market today is RME Digiface USB - which is a wonderful device, but about 4x more expensive and overpowered than it should be if all you need is to split ADAT into 4x stereo DAC outputs :)
It works as expected. I may sell preassembled units at some point. :)

Over the holiday, I have been working on a little firmware for the RP2040 (Pi Pico), which may be of interest to some. It creates a stereo USB audio device and outputs 2.1 channels using a pair of SPDIF outputs, with 10 PEQ filters per channel. Left/right on the first SPDIF and summed subwoofer channel on the second.

1767298123348.png
1767298110000.png


The filters are configurable in realtime via USB and I'll soon be writing a simple application for GUI control.

RP2040 boards can be found for less than €5, so I believe this to be rather excellent value for money. I have also been investigating the possibility of using direct PWM synthesis for the subwoofer channel, as it requires a sample rate of only about 350Hz. This would eliminate the need for a second DAC for the subwoofer.
 
Last edited:
So, I have pivoted to direct PDM output for the subwoofer channel via PIO. With 32x oversampling at 3MHz, this yields a 90dB SINAD up to about 500Hz. Perfectly adequate for a subwoofer and there remains room for improvement. It simply requires an RC filter and AC coupling capacitor at the output.

Other enhancements have included the introduction of a preamp control for all three channels, a Commit command that writes the current configuration to flash (4KB journaled sector with wear levelling) and a Bypass toggle to enable or disable all filters.

On the horizon is delay control for each channel, flags to use the Pico Audio module in place of PDM for the subwoofer output and possibly Bluetooth (LDAC) support. I have been making use of various LLMs since commencing this project and must admit that they have increased my productivity immensely. :oops:

For those interested, input to output latency with all filters active (now 15 per channel) is less than 5ms.
 
Today's progress has been in the control application. We now have realtime peak monitoring for all audio channels, as well as activity monitors for both CPU cores. Core 0 handles USB audio, biquads, routing and output. Core 1 handles PDM generation for the subwoofer output channel.

With a 32-bit signal chain, the RP2040 at 240MHz can comfortably accommodate ten filters per master channel and two filters per output channel. I may migrate to an RP2350, as the price is almost identical and it offers a floating point unit, which would dramatically increase performance in this application.

1767775309203.png


Everything is working well and appears stable. I have named the project DSPi and it will soon be headed to GitHub.
 
How about making the type of sub output (spdif/pdm) optional? I can imagine either being preferable depending on situation, and you've already implemented both.
 
How about making the type of sub output (spdif/pdm) optional? I can imagine either being preferable depending on situation, and you've already implemented both.
I do have plans to make the subwoofer output switchable between SPDIF, PDM and I2S (Pico Audio hat) via the console application. It's going to require some non-trivial architecture restructuring, so I may either leave it until all of the critical functions (such as delay) are complete or simply create a separate build for each output type.
 
Further progress on the console application. I am quite pleased with the present direction. Per-channel delays have been added to the firmware and the PDM and SPDIF output latency has been synchronised, with the total latency being 4ms.

1767856042369.png


This is the dashboard view, which provides an overview of all filters, channels and parameters in real time. Selecting a channel solos the chart display (though it can be overridden by clicking other channel pills beneath) and allows filters for that channel to be edited.

I have published the firmware to GitHub. The codebase will eventually need to be refactored, so it's quite messy the moment but it works. I will be publishing the macOS console application shortly, along with a simple Python script with all control functions implemented.

Upcoming functions include the ability to import and export filter text files and WAVs from REW.
 
Last edited:
Another development update. The last week has primarily been spent polishing the firmware and squashing bugs but I have had the chance to implement a few major functions.

PDM output is now extremely clean and could conceivably be used as a DAC in its own right. It far exceeds the performance necessary for a subwoofer output but I have a full core dedicated to it, so decided to fully optimize it.

1768611041576.png


One of the major new functions is the ability to load and save all active parameters using the onboard flash ("Commit Parameters"). This includes PEQ filters, channel delays, bypass states and preamp settings. All saved parameters are loaded automatically when the firmware boots, so the DSPi Console application is only needed when one wishes to make adjustments.

The "Revert to Saved" option resets the active parameters to their saved states in the event that they have been modified. "Factory Reset" clears all active parameters but does not clear them from flash unless "Commit Parameters" is then selected. All commands trigger confirmation prompts to reduce accidents.

1768612036235.png

Other improvements are less obvious:
  • Channel peak and CPU core utilization meters are now fetched as a single data packet in order to ensure synchronization between channels.
  • Buffer overrun and underrun counts for each component have been added to the "Stats for nerbs" window.
  • An additional USB interface has been created to facilitate driverless control under Windows.
Finally, the codebase has been refactored in a new branch, which contains all of the above enhancements and will soon be merged to main. I have also published the DSPi Console application to GitHub and will soon begin work on a Windows port using C# and WinUI3. If anybody wishes to contribute bug fixes or enhancements, I would be delighted.

I am currently working on integration with AutoEQ for headphones, REW import support and user configurable presets in the DSPi Console application. My RP2350 has arrived and I will soon be developing a build for that, making use of the floating point unit to implement a 64-bit accumulator. Bluetooth LDAC support is also a possibility there.

It is my hope that this software will greatly lower the economical barrier for entry to user friendly DSP.
 
Last edited:
Another week filled with bug fixes, major functions implemented, a Windows port and a platform agnostic CLI application.

Beginning with the macOS application, I have pushed the first complete release.

1769244164673.png

Every component of the interface has received attention. Here is a non-exhaustive list of the small revisions:

  • Application window migrated to the unified titlebar layout.
  • Global elements (utilisation meters, preamp) section of the sidebar now matches the upper half in style.
  • Excess rows removed from the output channel filters list in dashboard view.
  • Unnecessary divider lines removed to reduce interface clutter.
  • Window resize constraints implemented to prevent users from breaking the layout via resizing.
  • Unnecessary padding removed throughout the interface.

Now for the major changes. I have implemented full AutoEQ integration.

Screenshot 2026-01-20 at 17.25.29.png

The application includes a full copy of the AutoEQ database, complete with browser, search and favorites functionality. An update function enables the database to be updated either directly via the AutoEQ repository or from a user-supplied JSON. Once applied, the selected profile's filters are automatically loaded into the master channel PEQ slots and the preamp value is set.

1769245061838.png



The second major change is the introduction of import and export support for filters. Standard REW filters in text format are supported for import and the user can select the channels to which they are applied.

Screenshot 2026-01-20 at 17.26.22.png
1769245396289.png


The export function saves using a format devised specifically for this application, as it includes filters for multiple channels. When importing, the application automatically determines whether the file is REW standard or DSPi standard and presents the appropriate options. If it is the latter, the user is asked which channel's filters should be imported.

Screenshot 2026-01-20 at 17.27.08.png


I will soon be implementing export options so that users can choose to export specific channels in REW/Apo format. That's it for the macOS version at the moment.

Next we have the Windows port, to which I have dedicated a great deal of time this week.

1769246201204.png


My objective for the Windows port was to create a native Windows (WinUI 3, C#) application that matches the macOS version as closely as possible, both in form and function. All of the AutoEQ, import, export, load and save functionality is accessible via the gear menu, although I may later revise this design decision. This port is now available via GitHub and as always, I welcome code contributions.

Finally, we have the platform agnostic CLI application, written in Python. The source for this one is not yet available but that will change once my refactor is complete. It possesses all of the same functionality found within the GUI-based applications (including AutoEQ!) but runs on almost any platform without additional work.
Screenshot 2026-01-22 at 00.17.23.png

My intention is for this to be a CLI application that can be used comfortably without knowing a single command. Every command and parameter is easily discoverable and every step of syntax is autocompleted.

That's it for today. There's going to be a rather comprehensive video on the YouTube channel once I am satisfied with the level of polish within these applications and the firmware itself. The next major update will include compatibility with the RP2350. With the advent of its floating point unit, this will mean more filter slots, 64-bit accumulation and potentially more sophisticated algorithms like loudness compensation and psychoacoustic bass.
 

Attachments

  • Screenshot 2026-01-20 at 17.26.22.png
    Screenshot 2026-01-20 at 17.26.22.png
    202.7 KB · Views: 36
  • 1769245357840.png
    1769245357840.png
    50.2 KB · Views: 35
Another highly productive week. Beginning with the major update, we now have comprehensive RP2350 support!

1770181953768.png


This board is simply a magnificent DSP. In the screenshot above, what you see is the RP2350 running with 50 active PEQ filters. All filters are computed on core 0, which is at just 67% utilization. In addition to that, we now have a full 32-bit float audio pipeline with 64-bit accumulators.

The new mixed precision audio pipeline is possible due to a combination of the RP2350's floating point unit and its double precision co-processor.

The subwoofer PDM output has also received a major performance enhancement on both the RP2040 and RP2350. It now makes use of 256x oversampling and noise shaped dither, which increases SNR significantly. Listening to this output full range, you would never imagine that it doesn't originate from a DAC. At this point, I don't believe there is any reason to use a SPDIF or I2S output for the subwoofer; especially given current plans to implement a 2Vrms differential output and raise the SNR even further.

Speaking of the RP2040, further optimization was achieved by replacing several C-based multiplication functions in the main DSP loop with Assembly. With the resulting freed cycles, I now have the ability to implement a full 50 filters (10 per channel) on this board by handling the subwoofer channel's filters on core 1. This will be realized in a commit quite soon. Bear in mind that we still have a 32-bit fixed point architecture on RP2040 but the maximum number of cascaded biquads that will ever occur is 20 (input + output), so this is not really a problem.

Finally, we have the minor enhancements. Additional system statistics GET commands have been added for core temperature (celsius), sample rate, clock frequency and voltage. All of these are documented on the repository.

1770184159474.png


You may have noticed the gradients in some of DSPi Console's graph lines.

1770183884621.png


It occurred to me that in many situations (such as headphone AutoEQ profiles), two or more channels will likely contain the same filter settings. Rather than stacking and obscuring identical channels, I decided that a simple gradient between the two channel colors would serve to communicate this information effectively.

I am absolutely ecstatic with the progress that I have been able to make with this project. In its present state, the firmware is highly robust and with the cross platform desktop clients, should be plug-and-play for almost anybody.

Upcoming features include dynamic loudness compensated volume control, psychoacoustic bass and Bluetooth LDAC support for RP2350 boards with the appropriate IC.

The thought had also crossed my mind to draft a simple hat-type board that makes use of two TAD5212 DACs. They are affordable at just €6 each, exhibit a SINAD of about 104dB and are capable of delivering 64mW into 16 Ohms.

That's all for today. Whoever's been playing with this, have fun! :D
 
This is really great progress! How is the SPDIF
done now? Is that just a software implementation on a GPIO? If so, how feasible would it be to add a few more channels? That would certainly make this project super interesting for a lot more tinkerers. There also seems to be a software SPDIF input module
available. Could be a nice addition as well for those that don’t want to use a PC as a source. You’ll quickly need a channel matrix mixer if you were to add more inputs and outputs.

How is the clocking handled?

Frankly, this project might deserve its own dedicated thread. Might give it more exposure :)
 
This is really great progress! How is the SPDIF
done now? Is that just a software implementation on a GPIO? If so, how feasible would it be to add a few more channels? That would certainly make this project super interesting for a lot more tinkerers. There also seems to be a software SPDIF input module
available. Could be a nice addition as well for those that don’t want to use a PC as a source. You’ll quickly need a channel matrix mixer if you were to add more inputs and outputs.

How is the clocking handled?

Frankly, this project might deserve its own dedicated thread. Might give it more exposure :)
Thank you!

The SPDIF BMC is implemented via the PIO state machines, which is a little bit fancier than bit-banged GPIO. I can certainly add more inputs (SPDIF, I2S, Bluetooth). The only limitation is that they can't be mixed; one would switch to their desired input. Mixing inputs would mean mixing clock domains and ASRC is impractical on these boards.

Clocking is dynamic and it's built around the requirement of getting integer PIO clock dividers (in this case for SPDIF output) while ensuring there are enough free cycles to handle DSP and PDM. I ultimately settled on 288MHz as the "sweet spot" for a 48KHz sample rate. The SPDIF BMC needs to have a bit clock of 12.288MHz at 48KHz, so 288MHz allows me to use a 23.4375 divider and end up with exactly that value.

When switching to 44.1KHz, the core clock is switched to 264.6MHz for the same reason. The reduced sample rate offsets the reduced cycles available for processing. Likewise, I can use the same dividers for the PDM output bit clock.

I might put a dedicated thread together tomorrow evening. :)
 
Back
Top Bottom