Audio DSP FX Processor
An ESP32-Pico-Kit with ADAU1701 as high-quality I²S audio codec with built-in audio DSP core.
Elektor project 230510
Basically, the Audio DSP FX Processor board is an ESP32 microcontroller with high-quality audio in- and outputs added to it. Basically, as it has much more to offer than just that. What sets the Audio DSP FX Processor apart from other, somewhat similar (on first sight) boards is that the audio codec (from COder/DECoder, in other words, the ADC & DAC) integrates a DSP capable of processing audio all by itself. This handy feature makes the board not only powerful, but also super flexible and versatile.
The I²C bus allows controlling the DSP from another processor like the ESP32 or an Arduino UNO connected to the extension port. The DSP can use SPI for this too, but we chose I²C.
This bus is also available for reading from or writing to the EEPROM. As an example, when the ADAU1701 is in what is called Selfboot mode, it expects its program to be stored in this EEPROM. The ESP32 can load the EEPROM with a DSP program received from another computer, wirelessly or over USB.
The fourth bus runs from the ESP32 to the DSP and is for analog signals that can be used inside the DSP to control parameters of DSP algorithm blocks. This bus has four channels.
The audio I/O bus consist of two input channels and four output channels. The outputs are filtered by either passive or active filters, the inputs are filtered inside the DSP.
Besides the signals mentioned thus far, the ESP32 also features a USB-to-serial converter and a MIDI input (optically isolated) and a MIDI output. Up to four potentiometers are available for either controlling the DSP or for some other purpose.
Last but not least, the ESP32 has a radio for Wi-Fi and Bluetooth communication, symbolized by the antenna symbol.
IC1 is the ADAU1701 audio DSP. The circuit that surrounds it, is an almost verbatim copy-paste from the DSP’s datasheet. The only frivolity I allowed for is jumper JP1 that lets you select the clock source for the DSP.
The audio output filters (IC2, IC4, IC5 & IC6) are implemented as four completely separated channels without any op-amp sharing between channels. Not only did this simplify drawing the printed circuit board, but it also allows for mounting only the parts required for a certain desired audio output configuration (i.e. 2-channels with passive filters of full-blown 4-channel with active filters. Note that the price difference is minimal).
The four analog signals that can control parameters inside the DSP connect to MP9, MP2, MP3 and MP8 (ADC0 to ADC3, in that order). Depending on the position of a solder jumper (R16, R13, R7 & R9), the signal can either be a potentiometer or coming from the analog multiplexer (IC10 and IC11). The latter is required because the ESP32 has only two analog outputs. In case a potentiometer is routed to the DSP, be sure to remove its corresponding multiplexer series resistor (R44, R46, R47, R45). Also, in this case adjust P5 so that the hot side of the potentiometers is 3 V. When all potentiometers are connected to the ESP32, adjust P5 to get 3.15 V as this slightly improves their dynamic range inside the ESP32.
The I²S bus is a bit of a headache until you figure it out. The ADAU1701 supports both I²S master and slave modes, and so does the ESP32. So, who will be master, and who will be slave? As it turns out, there is only one solution because the ESP32 software libraries do not (yet) support I²S slave mode. Therefore, the ESP32 must be the master. Problem solved? Almost.
A subtle (undocumented?) detail of the ADAU1701 is that it requires the I²S clock signals to be synchronous to its master clock. If not, it mutes the audio outputs, something we don’t want. The only way to ensure synchronicity when the DSP is the I²S slave, is by clocking the DSP from the ESP32. This is where JP1 comes in. It allows choosing the DSP clock source: crystal X1 or the ESP32’s MCLK signal. Therefore, when I²S is to be used, make sure to short pins 2 & 3 of JP1. If the I²S bus is not needed, short pins 1 & 2 of JP1.
The ESP32 comes in the shape of an ESP32-Pico-Kit, an easy-to-use module with a USB-to-serial converter and a 3.3 V power supply on-board. Using a module instead of mounting the ESP32 directly onto the main board saves a lot of antenna-matching and other RF headaches and permits to mount the module only when it is needed.
The DSP is powered from IC9, which in turn is powered from either the USB port or from IC8. The observant reader may wonder why there is no protection diode like D3 in the 5 V supply coming from the ESP32 module. The reason is that this diode is already present on the ESP32 module.
A word about the MIDI interface. It is a straightforward optically isolated input and a non-isolated output but connected to a 4-way 3.5 mm jack socket (TRRS, tip-ring-ring-sleeve) due to board space constraints. Most people interested in MIDI will need only the input and use a TRS cable. Such a cable will short the MIDI output (pin R2 of K5) to ground, which is why R36 is not mounted by default. Mount R36 (82 Ω) to enable the output and use a suitable cable.
LED1 is available as a user-programmable LED, practical when debugging software or as a mode indicator or whatever.
In the Arduino IDE, open an example by clicking Files ⇾ Examples and scrolling down to the section ‘Examples from Custom Libraries’). Here you should see an entry for the Elektor_AudioDSP library. Click on it and choose an example.
Note that entries with an arrow to the right (e.g. ‘AudioTools’) require a third-party library with the name of the entry. I.e., examples in the AudioTools entry require the library ‘AudioTools’. Some of these libraries can be installed through the IDE’s Library Manager as described above, but not all. The link to the library is included in the sketch.
An example consists of an Arduino sketch and, in most cases, an executable for the DSP to be loaded into the board’s EEPROM. The comments at the top of the sketch tell you how to set the board’s jumpers and how to use the example. The example takes care of everything. Simply load a sketch and upload it to the board. If the EEPROM needs programming, the sketch will do it automatically.
The examples that use a DSP program include the SigmaStudio project for it. After installing the Elektor_AudioDSP library, you can find the examples in:
A collection of precompiled DSP executables can be found in the file adau1701_e2prom_collection.h included in the Elektor_AudioDSP library. The SigmaStudio project files used to generate these executables are in the ‘extra’ folder of the library.
Included amongst others are two generic executables that simply pass audio data from the ESP32 to the ADAU1701 using I²S: i2s_pass_through_44.1khz and i2s_pass_through_48khz. The only difference between them is the sample rate. These two executables turn the DSP into a stereo audio output on connector K3 (with a sine generator on connector K4).
Basically, the Audio DSP FX Processor board is an ESP32 microcontroller with high-quality audio in- and outputs added to it. Basically, as it has much more to offer than just that. What sets the Audio DSP FX Processor apart from other, somewhat similar (on first sight) boards is that the audio codec (from COder/DECoder, in other words, the ADC & DAC) integrates a DSP capable of processing audio all by itself. This handy feature makes the board not only powerful, but also super flexible and versatile.
Specifications
- ADAU1701 28-/56-bit, 50 MIPS digital audio processor supporting sampling rates of up to 192 kHz.
- ESP32-PICO-D4 32-bit dual-core microcontroller with Wi-Fi 802.11b/g/n and Bluetooth 4.2 BR/EDR and BLE
- 2× 24-bit audio inputs (2 VRMS, 20 kΩ)
- 4× 24-bit audio outputs (0.9 VRMS, 600 Ω)
- 4× control potentiometer
- MIDI in- and output
- I²C expansion port
- Multi-mode operation
- Power supply: 5 VDC USB or 7.5 VDC – 12 VDC (barrel jack, center pin is GND)
Applications
- Bluetooth/Wi-Fi audio sink (e.g., loudspeaker) & source
- Guitar effect pedal (stomp box)
- Music synthesizer
- Sound/function generator
- Programmable cross-over filter for loudspeakers
- Advanced audio effects processor (reverb, pitch shifting, etc.)
- Internet-connected audio device
- DSP experimentation platform
- Wireless MIDI
- MIDI to CV or vice versa
- Etc.
Circuit Overview
A functional block diagram is available as an attachment below. It shows two main blocks, the ESP32 and the ADAU1701 connected to each other with multiple buses. In the center, we find the I²S bus for transporting audio signals between the two processors. If the DSP takes care of all the audio processing, this bus is not used.The I²C bus allows controlling the DSP from another processor like the ESP32 or an Arduino UNO connected to the extension port. The DSP can use SPI for this too, but we chose I²C.
This bus is also available for reading from or writing to the EEPROM. As an example, when the ADAU1701 is in what is called Selfboot mode, it expects its program to be stored in this EEPROM. The ESP32 can load the EEPROM with a DSP program received from another computer, wirelessly or over USB.
The fourth bus runs from the ESP32 to the DSP and is for analog signals that can be used inside the DSP to control parameters of DSP algorithm blocks. This bus has four channels.
The audio I/O bus consist of two input channels and four output channels. The outputs are filtered by either passive or active filters, the inputs are filtered inside the DSP.
Besides the signals mentioned thus far, the ESP32 also features a USB-to-serial converter and a MIDI input (optically isolated) and a MIDI output. Up to four potentiometers are available for either controlling the DSP or for some other purpose.
Last but not least, the ESP32 has a radio for Wi-Fi and Bluetooth communication, symbolized by the antenna symbol.
The Circuit
The schematic of the Audio DSP FX Processor board is available as an attachment below.IC1 is the ADAU1701 audio DSP. The circuit that surrounds it, is an almost verbatim copy-paste from the DSP’s datasheet. The only frivolity I allowed for is jumper JP1 that lets you select the clock source for the DSP.
The audio output filters (IC2, IC4, IC5 & IC6) are implemented as four completely separated channels without any op-amp sharing between channels. Not only did this simplify drawing the printed circuit board, but it also allows for mounting only the parts required for a certain desired audio output configuration (i.e. 2-channels with passive filters of full-blown 4-channel with active filters. Note that the price difference is minimal).
The four analog signals that can control parameters inside the DSP connect to MP9, MP2, MP3 and MP8 (ADC0 to ADC3, in that order). Depending on the position of a solder jumper (R16, R13, R7 & R9), the signal can either be a potentiometer or coming from the analog multiplexer (IC10 and IC11). The latter is required because the ESP32 has only two analog outputs. In case a potentiometer is routed to the DSP, be sure to remove its corresponding multiplexer series resistor (R44, R46, R47, R45). Also, in this case adjust P5 so that the hot side of the potentiometers is 3 V. When all potentiometers are connected to the ESP32, adjust P5 to get 3.15 V as this slightly improves their dynamic range inside the ESP32.
The I²S bus is a bit of a headache until you figure it out. The ADAU1701 supports both I²S master and slave modes, and so does the ESP32. So, who will be master, and who will be slave? As it turns out, there is only one solution because the ESP32 software libraries do not (yet) support I²S slave mode. Therefore, the ESP32 must be the master. Problem solved? Almost.
A subtle (undocumented?) detail of the ADAU1701 is that it requires the I²S clock signals to be synchronous to its master clock. If not, it mutes the audio outputs, something we don’t want. The only way to ensure synchronicity when the DSP is the I²S slave, is by clocking the DSP from the ESP32. This is where JP1 comes in. It allows choosing the DSP clock source: crystal X1 or the ESP32’s MCLK signal. Therefore, when I²S is to be used, make sure to short pins 2 & 3 of JP1. If the I²S bus is not needed, short pins 1 & 2 of JP1.
The ESP32 comes in the shape of an ESP32-Pico-Kit, an easy-to-use module with a USB-to-serial converter and a 3.3 V power supply on-board. Using a module instead of mounting the ESP32 directly onto the main board saves a lot of antenna-matching and other RF headaches and permits to mount the module only when it is needed.
The DSP is powered from IC9, which in turn is powered from either the USB port or from IC8. The observant reader may wonder why there is no protection diode like D3 in the 5 V supply coming from the ESP32 module. The reason is that this diode is already present on the ESP32 module.
A word about the MIDI interface. It is a straightforward optically isolated input and a non-isolated output but connected to a 4-way 3.5 mm jack socket (TRRS, tip-ring-ring-sleeve) due to board space constraints. Most people interested in MIDI will need only the input and use a TRS cable. Such a cable will short the MIDI output (pin R2 of K5) to ground, which is why R36 is not mounted by default. Mount R36 (82 Ω) to enable the output and use a suitable cable.
LED1 is available as a user-programmable LED, practical when debugging software or as a mode indicator or whatever.
Getting Started
Out of the box with an empty EEPROM, the board doesn’t do anything. Therefore, the first step is to load a program into the EEPROM. There are several ways to do this, but the easiest is by using the ESP32-Pico-Kit. Follow the steps below:Prepare the board
- Plug the ESP32-Pico-Kit module on the main board with the USB connector pointing to the side (and its antenna near the center of the main board).
- Place a jumper on pins 2 & 3 of JP1 (position ‘ext. MCLK’).
- Place a jumper on pins 2 & 3 of JP2 (‘Selfboot’).
- Connect the micro-USB port of the ESP32-Pico-Kit to a free USB port on a computer. The power LED on the ESP32-Pico-Kit should light up (red) and the computer should detect a new serial port. If the port is not found, install the driver for the CP2101 USB-to-serial converter mounted on the ESP32-Pico-Kit. For details, please see [3].
Prepare your computer
- Launch the Arduino IDE (this project was developed using IDE version 1.8.19).
- From the Tools menu, select the Board ‘ESP32 PICO-D4’. If the ESP32 PICO-D4 isn’t listed in the Boards list, install the ESP32 Boards Package first (this project was developed using ESP32 core 2.0.17). For details on how to do this, please refer to the tutorial at [2]. Once the Boards Package is installed, you should be able to select the ESP32 PICO-D4.
- From the Tools menu, select the correct Port. If the port is not found, install the driver for the CP2101 USB-to-serial converter mounted on the ESP32-Pico-Kit. For details, please see [3].
- In the Arduino IDE, open the Library Manager (Tools menu -> Manage Libraries…). Search for ‘Elektor’. You should find a library named ‘Elektor_AudioDSP’. Install it. By default, the most recent version will be installed. Normally, there is no reason to install an older version (unless you want more bugs and less options). The library can also be downloaded from GitHub at [4] and installed manually.
Software Support
A library supporting the board and including application examples can be downloaded from GitHub. It can also be installed using the Library Manager of the Arduino IDE. Open the manager and search for the library Elektor_AudioDSP.In the Arduino IDE, open an example by clicking Files ⇾ Examples and scrolling down to the section ‘Examples from Custom Libraries’). Here you should see an entry for the Elektor_AudioDSP library. Click on it and choose an example.
Note that entries with an arrow to the right (e.g. ‘AudioTools’) require a third-party library with the name of the entry. I.e., examples in the AudioTools entry require the library ‘AudioTools’. Some of these libraries can be installed through the IDE’s Library Manager as described above, but not all. The link to the library is included in the sketch.
An example consists of an Arduino sketch and, in most cases, an executable for the DSP to be loaded into the board’s EEPROM. The comments at the top of the sketch tell you how to set the board’s jumpers and how to use the example. The example takes care of everything. Simply load a sketch and upload it to the board. If the EEPROM needs programming, the sketch will do it automatically.
The examples that use a DSP program include the SigmaStudio project for it. After installing the Elektor_AudioDSP library, you can find the examples in:
[path-to-your-Arduino-folder]\sketchbook\libraries\Elektor_AudioDSP\examples\
A collection of precompiled DSP executables can be found in the file adau1701_e2prom_collection.h included in the Elektor_AudioDSP library. The SigmaStudio project files used to generate these executables are in the ‘extra’ folder of the library.
Included amongst others are two generic executables that simply pass audio data from the ESP32 to the ADAU1701 using I²S: i2s_pass_through_44.1khz and i2s_pass_through_48khz. The only difference between them is the sample rate. These two executables turn the DSP into a stereo audio output on connector K3 (with a sine generator on connector K4).
Discussion (1 comment)