I recently was working on an ADAU1701 project where I wanted to select from multiple possible filter banks. My first approach was to create multiple filters in the project, split the audio signal to go through all of the filters, and then select the desired output using a multiplexer. While this approach worked, it required a lot of program instructions. In fact, it was filling up the entire program memory!
Here's a simple example illustrating this approach:
Unfortunately, using branched filter banks will drastically increase the number of instructions executed in a program, even though only one filter bank is being used at any given time. Here's the reason why:
The ADAU1701 SigmaDSP is a steam-based processor. It has a deterministic program counter. The program counter always steps through from the beginning of the program to the end of of the program. This happens on every sample. When the SigmaStudio project is compiled, all of the algorithms in the project are converted into program instructions and are assigned a location in program memory. This happens regardless of whether the actual audio path for individual algorithms is being used at any given time.
This means that all algorithms will occupy space in program memory, and since the program counter is deterministic, every instruction will be executed on every frame of the program. As a result, in my example above, both filters will be executed every time the program loops, even though only one output path is being used. That's simply the nature of the SigmaDSP core architecture.
So, how can I get multiple filters in parallel, and only select one set of filters at a given time? The solution to this problem is to use index-selectable filters.
Because of the nature of the SigmaDSP architecture, it is wasteful to put multiple sets of filters in the project if only one path is going to be used at any given time. So, my first approach was not the best way of solving the problem. In this case, instead of creating multiple "instances" of the filters, it is better to create a single "instance", and to store multiple sets of filters in memory instead. This is usually much better from a resource perspective, since parameter memory is more abundant than program memory.
Here is an example of an algorithm in SigmaStudio that implements a single "instance" of a filter and allows users to store multiple sets of parameters for that filter: https://wiki.analog.com/resources/tools-software/sigmastudio/toolbox/filters/general2ndorderindexselectable
The red index input pin for this cell selects a single set of filter coefficients from the different options in memory. This way, only one filter is executed per audio sample, but multiple options for the filter coefficients are stored in memory.
If one filter is not enough, then there is another option in the SigmaStudio library that allows users to store entire banks of filters that can be recalled using an index. The IdxSelectable Indp. Multiple Band Filter is a great example:
Here is an example implementing this approach:
This implements the same functionality as my original approach, but uses fewer program instructions!
If you want to learn more, here are some more resources...
- Filter examples, including index filters: https://wiki.analog.com/resources/tools-software/sigmastudio/tutorials/filterexamples
- EngineerZone thread showing how to select EQ presets with GPIOs: http://ez.analog.com/thread/14552
- Application note including an example of an index-selectable filter: http://www.analog.com/static/imported-files/application_notes/AN-951.pdf