0% found this document useful (0 votes)
121 views10 pages

Bluetooth Audio Digital Signal Processing An Ardui

1. The document describes a framework for playing audio over Bluetooth using an Arduino and an ESP32 microcontroller with digital signal processing capabilities. 2. Key components include an ESP32, Adafruit I2S Stereo Decoder, and necessary wiring. Software includes a btAudio library to stream and process audio data. 3. The ESP32 can perform tasks like high-pass and low-pass filtering on the audio in real-time using the btAudio library and digital signal processing code.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
121 views10 pages

Bluetooth Audio Digital Signal Processing An Ardui

1. The document describes a framework for playing audio over Bluetooth using an Arduino and an ESP32 microcontroller with digital signal processing capabilities. 2. Key components include an ESP32, Adafruit I2S Stereo Decoder, and necessary wiring. Software includes a btAudio library to stream and process audio data. 3. The ESP32 can perform tasks like high-pass and low-pass filtering on the audio in real-time using the btAudio library and digital signal processing code.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

instructables

Bluetooth Audio & Digital Signal Processing: an Arduino Framework

by the2ndTierney

Sum m a ry

When I think of Bluetooth I think of music but sadly most microcontrollers can't play music via Bluetooth. The
Raspberry Pi can but that is a computer. I want to develop an Arduino based framework for microcontrollers to play
audio via Bluetooth. To fully ex my microcontroller's muscles I'm going to add real-time Digital Signal Processing
(DSP) to the audio (high-pass ltering, low-pass ltering and dynamic range compression). For the cherry on top, I
will add a webserver that can be used to con gure the DSP wirelessly. The embedded video shows the basics of
Bluetooth audio in action. It also shows me using the webserver to perform some high-pass ltering, low-pass
ltering and dynamic range compression. The rst use of Dynamic range compression purposefully causes
distortion as an example of poor parameter choices. The second example eliminates this distortion.

For this project, the ESP32 is the microcontroller of choice. It costs less than £10 and is feature-packed with ADCs,
DACs, Wi , Bluetooth Low Energy, Bluetooth Classic and a 240MHz dual-core processor. The onboard DAC can
technically play audio but it won't sound great. Instead, I'll use the Adafruit I2S stereo decoder to produce a line-
out signal. This signal can easily be sent to any HiFi system to instantly add wireless audio to your existing HiFi
system.

Supplies:

Hopefully, most makers will have breadboards, jumpers, USB cables, power supply soldering irons and will only
have to spend £15 on the ESP32 and the stereo decoder. If not, all the parts required are list below.

An ESP32 - tested on ESP32-PICO-KIT and TinyPico - £9.50/ £24


Adafruit I2S Stereo Decoder - £5.51
Breadboard - £3-£5 each
Jumper wires - £3
Wired headphones/Hi-Fi system - £££
Push Headers or Soldering Iron - £2.10 / £30
Micro USB cable - £2.10/ £3
3.5mm to RCA connector/ 3.5mm jack to jack (or whatever your speaker needs) - £2.40/ £1.50
USB Power Supply - £5

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 1


1

3
2

1. 3.5mm jack to jack


2. USB power Supply
3. breadboard

https://youtu.be/bqw40B_JXUc

Step 1: Construction - the Breadboard

If you bought the ESP32-PICO-KIT you won't have to solder any pins as it comes pre-soldered. Simply place it on the
breadboard.

Step 2: Construction - Push Headers/soldering


Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 2
If you have a soldering iron, solder the pins to the to pay for a temporary soldering iron so I cut up some
stereo decoder according to the instructions on the push headers from pimoroni. I cut them up so they
Adafruit website. At the time of writing my soldering would t to the stereo decoder. This is not the best
iron was at work which was locked down. I didn't want solution (and not how the headers were intended to

be used) but it is the cheapest alternative to a for stability but this isn't necessary for this prototype
soldering iron. Slot the cut-up header on to the system. The pins to slot the headers into are vin, 3vo,
breadboard. You should only need 1 line of 6 pins for gnd, wsel, din and bclk.
the decoder. You can add another six to the other side

Step 3: Construction - Wire the Power Pins

Place the Stereo decoder on the push headers (vin, don't really care about the wire colour. The power pins
3vo, gnd, wsel, din and bclk pins) and rmly push are attached as follows:
them together. Again, this ideally should be done with
a soldering iron but I had to improvise. You will notice 3v3 (ESP32) -> to vin on stereo decoder
that all the wires in this instructable are blue. That's
because I didn't have any jumper wires so I cut 1 long gnd (ESP32) -> to gnd on stereo decoder
wire into smaller pieces. Also, I'm colourblind and

Step 4: Construction - I2S Wiring

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 3


To send the Bluetooth audio from the ESP32 to the transmitted. Not every microcontroller supports I2S
stereo decoder we are going to use a method of but the ESP32 has 2 I2S lines. This makes it an obvious
digital communication called I2S. The stereo decoder choice for this project.
will take this digital signal and turn it into an
analogue signal that can be plugged into a speaker or The wiring is as follows:
HiFi. I2S only requires 3 wires and is reasonably
straightforward to understand. The bit clock (bclk) 27 (ESP32) -> wsel (Stereo decoder)
line turns high and low to indicate a new bit is
transmitted. The data-out line (dout) turns high or low 25 (ESP32) -> din (Stereo decoder)
to indicate whether that bit has a value of 0 or 1 and
the word select line (wsel) turns high or low to 26 (ESP32) -> bclk (Stereo decoder)
indicate whether the left or right channel is being

Step 5: Installing the BtAudio Library

If you don't already have them installed install the should add my btAudio library to your Arduino
Arduino IDE and the Arduino core for ESP32. Once you libraries. To use the library you'll have to include the
have them installed visit my Github page and relevant header in the Arduino sketch. You'll see this
download the repository. Within the Arduino IDE in the next step.
under Sketch>>Include Library>> select "Add .ZIP
library". Then select the downloaded zip le. This

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 4


Step 6: Using the BtAudio Library

Once installed, connect your ESP32 to your computer via micro USB and then connect your stereo decoder to your
speaker with your 3.5mm wire. Before you upload the sketch you will need to change some things in the Arduino
editor. After you have selected your board you will need to edit the partition scheme under Tools >> Partition
Scheme and select either "No OTA (Large APP)" or "Minimal SPIFFS(Large APPS with OTA)". This is necessary because
this project uses both WiFi and Bluetooth which are both very memory heavy libraries. Once you've done this
upload the following sketch to the ESP32.

#include <btAudio.h>

// Sets the name of the audio device


btAudio audio = btAudio("ESP_Speaker");

void setup() {

// streams audio data to the ESP32


audio.begin();

// outputs the received data to an I2S DAC


int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);
}

void loop() {

The sketch can broadly be divided into 3 steps:

1. Create a global btAudio object that sets the "Bluetooth name" of your ESP32
2. Con gure the ESP32 to receive audio with the btAudio::begin method
3. Set the I2S pins with the btAudio::I2S method.

That's it on the software side! Now all you need to do is initiate the Bluetooth connection to your ESP32. Just scan
for new devices on your phone/laptop/MP3 player and "ESP_Speaker" will appear. Once you are happy that
everything is working (music plays) you can disconnect the ESP32 from your computer. Power it with the USB power
supply and it will remember the last code that you uploaded to it. This way, you can leave your ESP32 hidden
behind your HiFi system forever.

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 5


Step 7: DSP - Filtering

Ext e n d i n g t he R e c e i v e r w i t h D i g i t a l S i g n a l P r o c e s s i n g
If you followed all the steps (and I didn't leave anything out) you now have a fully functioning Bluetooth receiver
for your HiFi system. While this is cool it doesn't really push the microcontroller to its limits. The ESP32 has two cores
operating at 240MHz. That means this project is far more than just a receiver. It has the capacity to be a Bluetooth
receiver with a Digital Signal Processor (DSP). DSPs essentially perform mathematical operations on the signal in
real-time. One useful operation is called Digital Filtering. This process attenuates frequencies in a signal below or
above a certain cuto frequency, depending on whether you are using a high-pass or low pass lter.

Hi g h- p a s s lt ers
High-Pass lters attenuate frequencies below a certain band. I've built a lter library for Arduino systems based on
code from the earlevel.com. The main di erence is that I've changed the class structure to allow for the
construction of higher-order lters more easily. Higher order lters suppress frequencies beyond your cuto more
e ectively but they require much more computation. However, with the current implementation, you can even use
6th order lters for real-time audio!

The sketch is the same as the one found in the previous step except that we have changed the main loop. To enable
the lters we use the btAudio::createFilter method. This method accepts 3 arguments. The rst is the number of
lter cascades. The number of lter cascades is half the order of the lter. For a 6th order lter, the rst argument
should be 3. For an 8th order lter, it would be 4. The second argument is the lter cuto . I've set this to 1000Hz to
have a really dramatic e ect on the data. Finally, we specify the type of ler with the third argument. This should be
highpass for a high-pass lter and lowpass for a low-pass lter. The script below switches the cuto of this
frequency between 1000Hz and 2Hz. You should hear a dramatic e ect on the data.

#include <btAudio.h>

btAudio audio = btAudio("ESP_Speaker");

void setup() {
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);

void loop() {
delay(5000);
audio.createFilter(3, 1000, highpass);
delay(5000);
audio.createFilter(3, 2, highpass);
}

Lo w - p a s s lt ers
Low pass lters do the opposite of high pass lters and suppress frequencies above a certain frequency. They can
be implemented in the same way as high pass lters except that they require changing the third argument to
lowpass. For the sketch below I alternate the low-pass cuto between 2000Hz and 20000Hz. Hopefully, you'll hear
the di erence. It should sound quite mu ed when the low-pass lter is at 2000Hz.

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 6


#include <btAudio.h>

btAudio audio = btAudio("ESP_Speaker");

void setup() {
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);

void loop() {
delay(5000);
audio.createFilter(3, 2000, lowpass);
delay(5000);
audio.createFilter(3, 20000, lowpass);
}

Step 8: DSP - Dynamic Range Compression

B a c k g r o un d
Dynamic range compression is a signal processing method that tries to even out the loudness of the audio. It
compresses loud sounds, that rise above a certain threshold, to the level of quiet ones and then, optionally
ampli es both. The result is a much more even listening experience. This came in really useful while I was watching
a show with very loud background music and very quiet vocals. In this case, just increasing the volume didn't help
as this only ampli ed the background music. With dynamic range compression, I could reduce the loud
background music to the level of the vocals and hear everything properly again.

T he C o d e
Dynamic range compression does not just involve lowering volume or thresholding the signal. It's a bit more clever
than that. If you lower the volume quiet sounds will be reduced as well as the loud ones. One way around this is to
threshold the signal but this results in severe distortion. Dynamic range compression involves a combination of soft
thresholding and ltering to minimize the distortion one would get if you were to threshold/clip the signal. The
result is a signal where the loud sounds are "clipped" without distortion and the quiet ones are left as they are. The
code below switches between three di erent levels of compression.

1. Compression with distortion

2. Compression without distortion

3. No Compression

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 7


#include <btAudio.h>
btAudio audio = btAudio("ESP_Speaker");

void setup() {
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);
}

void loop() {
delay(5000);
audio.compress(30,0.0001,0.0001,10,10,0);
delay(5000);
audio.compress(30, 0.0001,0.1,10,10,0);
delay(5000);
audio.decompress();
}

Dynamic range compression is complicated and the btAudio::compress methods has many parameters. I'll try and
explain them (in order) here:

1. Threshold - The level at which the audio gets reduced (measured in decibels)
2. Attack time - The time it takes for the compressor to start working once the threshold has been
exceeded
3. Release time - The time it takes for the compressor to stop working.
4. Reduction Ratio - the factor by which the audio is compressed.
5. Knee Width - The width (in decibels) around the threshold at which the compressor partially
works(more natural sound).
6. The gain (decibels) added to the signal after compression (increase/decrease volume)

The very audible distortion in the rst use of compression is because the threshold is very low and both the attack
time and release time are very short e ectively resulting in a hard thresholding behaviour. This is clearly solved in
the second case by increasing the release time. This essentially causes the compressor to act in a much smoother
way. Here, I've only shown how changing 1 parameter can have a dramatic e ect on the audio. Now it's your turn to
experiment with di erent parameters.

T he Imp l e me n t a t i o n (t he ma g i c ma t he ma t i c s - o p t i o n a l )
I found that naively implementing the Dynamic range compression to be challenging. The algorithm requires
converting a 16-bit integer to decibels and then transforming it back to a 16-bit integer once you have processed
the signal. I noticed that one line of code was taking 10 microseconds to process stereo data. As stereo audio
sampled at 44.1 KHz leaves only 11.3 microseconds for the DSP this is unacceptably slow... However, by combining a
small lookup table (400 bytes) and an interpolation procedure based on Netwon's divided di erences we can obtain
nearly 17 bits precision in 0.2 microseconds. I've attached a pdf document with all the maths for the truly
interested. It's complicated, you've been warned!

Download
https://www.instructables.com/ORIG/FM9/PIMD/KBDNJHBC/FM9PIMDKBDNJHBC.pdf

Step 9: The Wifi Interface

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 8


Now you have a Bluetooth receiver capable of running real-time DSP. Sadly, if you want to change any of the DSP
parameters you will need to disconnect from your HiFi, upload a new sketch and then reconnect. This is clunky. To
x this I developed a webserver that you can use to edit all the DSP parameters without reconnecting to your
computer. The sketch to use the webserver is below.

#include<webDSP.h>
#include<btAudio.h>

btAudio audio = btAudio("ESP_Speaker");


webDSP web;

void setup() {
Serial.begin(115200);
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);

// replace with your WiFi ID and password


const char* ssid = "SSID";
const char* password = "PASSWORD";
web.begin(ssid,password ,&audio);
}

void loop() {
web._server.handleClient();
}

The code assigns an IP address to your ESP32 which you can use to access the webpage. The rst time you run this
code you should have it attached to your computer. That way you can see the IP address assigned to your ESP32 on
your serial monitor. If you want to access this webpage simply enter this IP address into any web browser (tested on
chrome).

By now we should be familiar with the method of enabling the Bluetooth and I2S. The key di erence is the use of a
webDSP object. This object takes your Wi SSID and password as arguments as well as a pointer to the btAudio
object. In the main loop, we continually get the webDSP object to listen for incoming data from the webpage and
then update the DSP parameters. As a closing point, it should be noted that both Bluetooth and Wi use the same
radio on the ESP32. This means that you might have to wait for up to 10 seconds from when you enter parameters
on the webpage to when the information actually reaches the ESP32.

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 9


Step 10: Future Plans

Hopefully, you've enjoyed this instructable and now have Bluetooth Audio and DSP added to your HiFi. However, I
think there's a lot of room for growth in this project and I just wanted to point out some future directions I might
take.

Enable Wi streaming of audio (for the best audio quality)


Use an I2S microphone to enable voice commands
develop a WiFi controlled equaliser
Make it pretty (breadboard doesn't scream great product design)

When I do get around to implementing these ideas I'll make more instructables. Or maybe someone else will get
these features implemented. That's the joy of making everything open source!

Bluetooth Audio & Digital Signal Processing: an Arduino Framework: Page 10

You might also like