An audio DSP built with the Espressif ESP32 LyraT for around $20.
In building my new home theater, I planned to dabble a bit into the DIY DSP world to try to tame some room anomalies without spending a bunch of cash. As I have experience in C development and the Arduino world, I figured I would try building my own inexpensive processor. I settled on the Espressif ESP32-Lyrat developer board as a platform as it is open source, cheap ($20), contains a fast processor (ESP32), and includes onboard WIFI as well as a 24-bit DAC/ADC (ES8388).
After some weeks of development, my DSP is now up and running and has been incorporated into my home theater.
A DSP is like an equalizer - on steroids. Using digital filters, it allows highly detailed control over a signal before it gets sent to an output device. Typically it is used to do things like adjust subwoofer behaviour (e.g. adding a bass bump at 30Hz), equalize a speaker's overall response, or compensate for how a room colors sound at specific listening positions. These are all possible with this $20 project. And with this DSP, you can either design the filters yourself or use a program like REW to generate the filters for you.
The DSP supports the following:
Filter settings, delays, etc. are controlled via updates to the source code, recompiling and uploading.
It's possible but unlikely if you take care. You should ALWAYS lower your amplifier level whenever you upload new firmware to the DSP. This is for two reasons;
The act of uploading into the DSP will generate a short burst of white noise at the tail end of the upload. The volume of this white noise cannot be controlled and can be quite loud.
IMPORTANT: If you are implementing your own biquads, the filters may become unstable. Unstable filters generate VERY LOUD RANDOM NOISE VERY QUICKLY that can easily damage speakers if the amplifier volume is set high.
ALWAYS lower your amplifier volume initially when testing new filter uploads. Keep in mind that this is an open development project and as such it is up to you to ensure that your equipment is kept safe.
You'll need:
IMPORTANT: This application currently only works with the development board shown above.
There are a number of other ESP32-Lyrat boards, but they are configured with different features that may or may not work properly with this code. My guess is that most of this code will work on the other boards, but some modifications would probably needed. Besides, most of the other LyraT boards are more expensive and have fewer useful features for a pure audio application.
Of course, keep in mind that a DSP does not have the ability to power speakers directly. You will also need an amplifier as you would with any other DSP.
You'll need two micro-USB power supply cables, as well as two stereo 3.5 mm audio cables. The former are used to power the DSP - a 1A 5V supply should be fine - and to interface with the ESP32 chip for uploads. Once the firmware has been uploaded the first time, you will be able to program the board over WiFi through the Arduino OTA interface, and will only need one cable for power after that. The two stereo cables are used to connect the board AUX input to a stereo source (e.g. receiver) and the board's HEADPHONE stereo output to an amplifier.
Optionally, you can also add a display to the DSP to show what it is doing. I have coded for a small 0.91" OLED that can readily be purchased on Amazon and will provide additional details on how to add it on request.
It's a lot more powerful, with 4.5 MB of memory and 2 CPUs running at up to 800 MHz. This makes it a good fit for this application. It also has WiFi and Bluetooth on board. Unless you are already developing for the ESP32, you will need to install the board through the Board Manager in the Arduino IDE. You can find instructions for installing the ESP32 boards here.
The specific ESP32 for the ESP32-Lyrat is the ESP32 Wrover. This is the one you need to pick from the board list once the ESP32 boards have been installed.
Beyond that, working with this board in Arduino is very similar to the ESP8266 with ONE important exception; when uploading the firmware from the serial port, you MUST press the RST and BOOT buttons in a certain sequence. THIS IS VERY IMPORTANT.
Here is the board layout:
As you initiate the serial upload you must (in the correct order):
Fortunately, once the firmware for the DSP has been loaded the first time, you will be able to upload over WiFi through the Arduino OTA.
You need a few things:
You will find it much easier to work with the ESP32 using the older Arduino 1.8.x IDEs. There are some annoying bugs in the Arduino 2.0.x IDE that make working with the EspressIf boards a bit of a pain. Until these get worked out, it's just easier to stick with the 1.8.x IDEs. If you don't aleady have a version installed, here is a link to these IDEs.
You will need to install the following libraries by downloading the .zip files and adding to your Arduino libraries directory:
Optional (only if display is added)
Current versions of these libraries should be fine.
The code is located in the GitHub repository here. All of the source files are contained in the ESP_LyraT_DSP directory. Like any other Arduino project, transfer these files to a new directory named ESP32_Lyrat_DSP in your Arduino application directory and you are good to go.
Just update the file named credentials.h with your WiFi SSID and password. The DSP will automatically connect to your network when started. It will also automatically reconnect if it should lose the connection.
You add your filters by updating the dsp_config.h file. Example configurations can be found in the Examples directories for different applications. You can specify filters either in frequency form or as biquads. Both sets are compiled into the program and uploaded with the firmware. Combined, the maximum filters you can have is 20 per channel.
The types of frequency filters that can be defined are:
User specified biquad filters are also supported in the dsp_config.h file in a similar fashion. Sequencing of the biquad filter coefficients is b0, b1, b2, a1, a2. Of course, it is up to the user to calculate the appropriate biquads for the filters they are implementing. Here is a link to a spreadsheet that will assist you in defining biquads if you decide to go this route.
In the dsp_config.h file, you specify the name of each output channel, amount of delay, gain, and mixing of the inputs. This allows for quite a bit of control.
For example:
Example configuration files for each of these situations is provided in the Examples directory.
You can define up to 20 filters per output channel. This includes your own filters and those imported from an external application like REW. If you try to upload more, the DSP will show an error in a serial or Telnet session, or on the OLED display if one is attached.
If you are familiar with REW, you simply export the EQ filters from the application and then insert the contents into the file called dsp_import.h. Note that you must use the filter export format called miniDSP_2x4_HD from REW, and that the contents must be pasted exactly as exported into the correct location in the dsp_import.h file.
If you are unfamilar with how to use REW to generate EQ filters, you will find the step-by-step process here. This example is for the MiniDSP, but the general process is essentially the same. Once the EQ file is exported, you simply copy and paste it into the dsp_import.h file. Use the example here as a template. If you make a mistake, an error will be generated and shown when you connect to the running DSP via Telnet or the Serial port, or on the OLED display if one is attached.
When you connect the board directly via the serial port, you can issue commands that provide information as to the board status including filter information as well as errors. When not directly connected to the serial port, you can also use Putty or any other Telnet application over WiFi to receive information from the DSP as it is running. Simply connect the telnet session to the DSP's IP address and use one of the commands below.
Uploading the DSP via WiFi employs the same steps as uploading to other Arduino boards. You can find a description of the overall proces here.
If you are interested in adding a display, let me know via GitHub e-mail and I will provide details.
Make sure you are using a good quality 5V power supply. Try different ones. If you can't seem to completely eliminate the noise, what you can do is add a bit of low level random noise in the DSP (called dither) to mask it. This is done by setting the variable DSP_DITHER to 1 in the file dsp_process.h.
If you have access to a 3D printer, you will find .STL files for the no display and OLED versions here.
For the no display version, you will need four 3 mm screws to secure the board to the base. For the OLED version, you will need an additional four screws to secure the display to the lid.
Not at the moment though I will likely add that capability in a future version. Stay tuned.
It is posssible to overdrive the DSP into clipping by either having input levels too high or by too much gain specified in the filters. The DSP will indicate this situation by flashing the green LED on the board. It will also display the number of times the input and output levels have clipped since boot up on the display if one is attached. This information is also shown through the 'i' command via the serial port/Telnet interface.
Note that the green LED will light when clipping occurs at either the input or output.
It's possible the ESP32 cannot connect to your WiFi due to a problem with WiFi or it could be a problem with the firmware code. Sometimes it's just a matter of unplugging and plugging the board and it will reconnect. If you've made changes to the code or made a mistake when configuring, the board may be in a reboot cycle. When this happens you will need to figure out and fix your changes and then re-upload to the board via the serial port.
There is a lot of information on Z-Transforms, IIR filters, biquads, etc. on the Internet, so best just to do a search. That said, here is a spreadsheet that will generate biquads for you without the need to understand the math.
You can change the plot layout by making changes to the dsp_plot.cpp file and recompiling. Setting FREQ_RANGE_LOW to 20.0 and FREQ_RANGE_HIGH to 120.0 in the code will change the plot as requested here.