Audio player with voice control using Arduino: a frequency analyzer based on the Goertzel algorithm
The sky’s the limit when it comes to creating cool projects using Arduino. This article presents an audio player done from the ground up using Arduino and other electronic components. This device performs the Discrete Fourier transform (DFT) using the Goertzel algorithm for recognizing audio frequencies and performing a set of commands. An 8x8 LED panel was used for displaying the audio frequencies, and a digital amplifier was applied for playing the audio.
I used the Arduino board in this project. Instead of buying ready-to-use boards for the microphone, I chose to create my own circuit since I had some electronic components to spare in my workbench. The implemented algorithm is based on DFTs, and it’s quite reliable and easy to understand.
In addition, I used two speakers in a closed plastic box for playing the audio. As a plus, you can add an LED matrix display to make this project even cooler.
The code used in this article is available on my GitHub:
An implementation of a spectrum analyzer in the Arduino Mini using the Goertzel algorithm. The figure below shows the…
Discrete Fourier transform
Before explaining the Goertzel algorithm itself, it’s important to know what is behind such approaches. DFTs are used in the majority of the devices that deal with digital signals. In other words, almost all devices that perform digital signal processing use DFTs. Remember, when we’re talking about digital signals, we’re referring to an audio signal, an image signal, etc. So, what that means is that your TV, computer, and radio does DFT behind the scenes.
Now that you know the importance of such matter, let’s see how it works. Keep in mind that the concepts presented here are the basic ones, and it should only be seen as a general overview of the Fourier theory.
In digital signal processing, all signals we deal with are analog. Our world is an analog world. You may wonder what an analog signal may look like. If that’s the case, an analog signal is a time-continuous signal, like the one shown above. Despite the fact that almost everything around us is analog, computers, on the other hand, are digitals. Therefore, all analogic signal must be transformed into a digital signal if we want to process it. This is when DFTs comes into play. We use it to convert an analog signal into a digital one.
I’m not going to dive too deep on this topic since it’s quite advanced to understand, so let’s keep it simple. So, let’s just say that the DFT makes it possible to transform an analogic signal (A) into a digital signal (B), and then we can use computers or DSPs to process it (C), and finally reconstructing the original one (D).
The Goertzel algorithm is an extremely efficient way of doing a DFT. The major difference between this computational approach from other DFT methods is the single real-valued coefficient it uses in each iteration. The downside of this analysis is that it has a higher order of complexity when compared with FFTs. However, for a small number of frequencies, this algorithm outperforms its counterparts when it comes to efficiency. Remember that we’re implementing this software in an Arduino, so hardware limitation is an important matter.
I used the article Embedded Systems Programming published by Kevin Banks in 2002 as a guideline to create the C code for this project. Unfortunately, I couldn’t find a link for this work, but you can check this link for a quick overview.
Again, I’ll not explain all the math behind this algorithm. We’ll see how it works in a practical application. In order to use this algorithm, we’ll need to do the following steps first:
- Decide the sampling rate.
- Choose the block size N.
- Precompute one cosine and one sine term.
- Precompute one coefficient.
For each one of those bullets points, there is an excellent explanation here.
So, since we’re using an Arduino Mini, we need to calculate the frequency we’re sampling our analog signal. For that, we need to divide the clock of our microcontroller by 2 to get the maximum sampling frequency since this is stated in the Nyquist–Shannon sampling theorem. So, since we’re using a 16 MHz processor, we’ll use a frequency of 9kHz and N = 115 samples for our implementation. The greater the value of N, the higher the frequency resolution will be.
The formulas we need to implement are these ones:
Now that we already know what we need to implement, we need to create a function in C to implement the logic presented.
Note that we need to run this function inside a loop. For testing, we’ll measure the result of this implementation with 8 frequencies by analyzing the LED matrix which gives us a representation of the amplitude of each frequency.
After playing each tone in the device, we got the following results:
It is clear that our algorithm worked. Even though we could notice some errors associated with the results, overall we could achieve a high resolution when it comes to frequency analysis.
I inputted an audio signal of 624 Hz in the device and wrote the results in a text file using the Arduino IDE. I then used Excel to plot a chart of the amplitude of all 8 frequencies we’re working with.
The yellow graph represents the amplitude (strength) of the 624 Hz signal. Note that all other frequencies were attenuated.
I wrote in this post’s title we’ll be able to recognize voice using this device. However, the reality is not quite true due to hardware limitations. We’ll be able to recognize some frequency tones and use them to perform commands. So, the goal here is to use the microphone to listen to the frequency of 4KHz and turn on our device automatically.
Bear in mind you can modify this project so it can recognize a specific audio pattern as well or even a word. So, the function will look like this:
Note that when we use a function generator for creating an audio signal of 4KHz, our device turns one and begins playing music.
We’ll need some electronic components for building this project. I bought all my components on AliExpress for around USD 30. Here are some of the major elements:
I used a 2x3W PAM8403 Class D amplifier in this project.
This module runs with a 5V input, and it can drive up to two speakers in stereo mode.
The price is around USD 5 and you can buy it here.
You can use any Arduino board you want to. I pick the Mini package since it’s quite handy when it comes to portability doe to its small size.
If you choose this one, bear in mind you’ll need an FTDI USB-to-TTL converter to write your code in the microcontroller.
I went with two pretty-cool-looking speakers that I salvaged from an old portable radio. However, you can buy them here from less them USD 3.
They have 3W of power, which goes in line with our amplifier.
This 8x8 LED panel definitely gives a plus in the project. besides being really cheap, only USD 2.50, it delivers high-quality representation of audio frequencies.
You can buy it here.
- Breadboard Board Universal PCB — USD 2
- Microphone Module with Amplifier 5V — USD 2
- External 5V 2A power supply or USB Power Bank — USD 4
- PJ32 Audio Jack with Cable — USD 2
Note that it consists of three major designs: the amplifier, the microphone, and the Arduino. At the bottom of it we’ll see the microphone hucked with an operational amplifier class D. On top of the diagram is located the Audio D amplifier board which will drive the two speakers. Finally, the 8x8 LED matrix is connected to the Arduino.
For powering this circuit I used a 5V@2A USB power bank. All components run at 5V.
I also used an NPN transistor as a switch for turning on the audio player as well as the LED matrix.
At the bottom of the PCB, I placed the microphone circuit.
Finally, I included a push-button switch for turning off the device.
I recorded a video of this project and upload it to YouTube
If you liked this project, and want to check out all the material and code necessary for building one on your own, click here.