Reduce MIPS Usage in a "complex" ADAU1701 2x4 DSP Project
Good morning :)
For educational purposes, I am trying to reproduce in SigmaStudio the functionality of a device based on the ADAU1701. The project runs at 48 kHz, and the DSP parameters are controlled in real time by an external MCU.
The signal flow is approximately:
2 × INPUT
each input:
→ signal level readout
→ volume control
→ mute
→ 5-band EQ
- PEQ
- low shelf
- high shelf
- direct biquad coefficient import
→ 2×4 routing matrix
4 × OUTPUT
each output:
→ HPF
→ LPF
→ 5-band EQ
- PEQ
- low shelf
- high shelf
- direct biquad coefficient import
→ volume control
→ delay
→ RMS compressor
→ mute
→ polarity inversion
→ signal level readout
The HPF and LPF can use slopes up to 48 dB/oct, which means up to four biquad sections for the HPF and four for the LPF on each output.
This gives a maximum of:
Input EQ: 2 × 5 = 10 biquads
Output EQ: 4 × 5 = 20 biquads
HPF + LPF: 4 × 8 = 32 biquads
Total: 62 biquads
My main problem is fitting all of this functionality within the ADAU1701 instruction budget.
I have already made several optimizations to reduce MIPS usage.
The volume controls use Gain (No Slew). I do not use separate Mute or Invert blocks, because I can implement these functions using the linear gain value:
+gain → normal polarity
-gain → inverted polarity
0 → mute
I also implemented the 2×4 routing matrix using a mixer instead of separate Mute and Add blocks, which resulted in a reduction in instruction usage.
For the EQ and HPF/LPF filters I use General 2nd Order in Double Precision. The filter coefficients are calculated by the MCU and updated in real time.
I tried replacing some filters with Single Precision versions, but at low frequencies and high Q values I observed noticeable problems with the audio signal. This is especially important for HPF/LPF filters that may operate around 25–80 Hz with narrow PEQ filters.
I also experimented with an RMS Compressor variant with Display. I noticed that it exposes additional values in trap.datrelated to its internal level detection and compression.
If one of these values represents the RMS level of the signal after compression, it could potentially allow me to remove the separate output level detector and save some instructions.
However, I would prefer to use trap.dat only as a last resort. I prefer solutions where parameters and addresses can be obtained through the standard files exported by SigmaStudio, such as PARAM.h.
The device I am trying to reproduce uses RMS metering. In my own final design, however, I would prefer Peak metering if it can be implemented with a reasonable instruction cost.
I am therefore looking for ways to further optimize this project without giving up Double Precision where it is really needed.
I am particularly interested in:
a more instruction-efficient way to implement a large number of DP biquads,
sharing computations between the compressor and level meter,
a cheaper way to implement HPF + LPF with slopes up to 48 dB/oct,
an instruction-efficient way to obtain Peak level readout,
any other common ADAU1701 optimization techniques that I may have overlooked.
Data RAM is not currently the main limitation — I can reduce the maximum delay length as needed.
I will attach the complete .dspproj project to the post.
Best regards
Bartek
2in_4out_diy_passfilter_reduce.dspproj
software
processors and dsp
Processors and Microcontrollers
adau1701
Hello Bartek,
Thanks for supplying your project!!
You are doing a lot of filtering. It is difficult to make those use less instructions. You did good to try to use single precision versions but you are correct that it is not good for low frequencies. It would be OK for something like the High-Frequency output of a crossover.
I took a quick look. It is going to be tough to squeeze out more instructions. You have done a good job with the signal flow. I suppose you could use two compressors on the stereo input rather than four on the individual outputs but with my pro-audio recording experience I know it would sound better on the individual outputs. So I do not have an obvious suggestion in my super quick look just now. I will need to study this and ask some of the SigmaStudio programmers for suggestions as well.
One option would be for you to program some custom assembly language programs but that has a huge learning curve!!
I will try to get back to you quickly. Send me a PM if you do not hear back from me in a few days. Make sure to also send me a friend request so I can reply!
Thanks,
Dave T
Hello DaveThib,
Thank you for taking the time to look into this.
Regarding the suggestion of using two compressors on the inputs instead of four on the individual outputs, in this particular project I am trying to reproduce the signal flow of an existing ADAU1701-based device as closely as possible. For that reason, at this stage I would like to keep the current signal flow as close to 1:1 as possible.
I am starting to consider that the original product may use custom, more highly optimized algorithms or its own assembly code. If that is the case, it may simply not be possible to reproduce all of its functionality using only the standard SigmaStudio blocks within the available instruction budget. In that case, I will have to accept some compromises and remove some functionality.
I am also open to learning assembly programming for SigmaDSP processors, but I do not think this is the right stage of the project for such a major change in approach.
I am very interested to hear any further suggestions!
Hello Bartek,
Quick question...
The Main router. Are you actually mixing signals or just sending the inputs to an output with no mixing? Using a MUX here might save some instructions. I will investigate this possibility but I need to know if you will mix the left and right inputs to any of the outputs?
Dave T
I would like to keep the ability to mix both input channels into the same output.
Each output should be able to receive:
- Left only,
- Right only,
- or Left + Right summed together.
I have also attached a screenshot from the application I am building to control this DSP project. Unfortunately, the UI is currently only in Polish, but it shows how the routing matrix works: each input-to-output connection can be enabled independently, and each output receives the sum of all active input connections.
Please log in to reply.
