This page is now depreciated and these articles have been replaced with new, see the menu “Basics->Audio->Dacs for Sound”.
Following on from the last article on using the ESP32’s DAC to play digitised sound we now move onto playing fully digitised sound in the form of WAV’s. The kit required is not much, see that last article for the build details. A supporting video is also available, click below if you want to watch it.
What are WAV’s?
A wav (or more fully wave file) is a simple file format for storing digital sound. It’s little more than the raw numeric data representing the sound wave (hence wave/wav file) with a little bit of header data bolted on at the start to help the program playing the data to know things like: is it stereo or mono, number of bits per sample and number of samples per second. One of the main advantages is that because it’s so simple with no compression most low power CPU’s can decode and play the files easily, even a late 1970’s early 80’s computer would have had little problem from a horsepower point of view. But unfortunately the disadvantage of no compression means that the files tend to be big, in fact huge compared to mp3’s etc. especially when we’re talking of audio that lasts a reasonable time and is not just a very short piece. In this respect those early computers with their limited storage just couldn’t cope. Of course given enough storage, huge files sizes are not a problem if your file fits within your available storage.
Playing back digital sound
So all we need to do is send the numbers representing the sound wave, at a point in time, to a DAC, connect that DAC to an audio amp and then onto a speaker. And that is it. The only thing we need concern ourselves with is how often we send the values to the DAC, this will govern the playback speed. For now I won’t go into detail as I suspect you just want some code to allow you to play wav’s, but suffice to say that this information is stored as a value per second near the start of the wav file and the code just needs to playback at this same rate for perfect sound.
The library
So I’ve written a library for the ESP32 that will take care of all the dirty nitty gritty aspects of playing back a wav file. The only thing I will say about it is that it will change in the near future as I add more features to it and some functions may or may not change as it develops. So with that in mind click the link below to download the library zip file.
Sample Code
The library comes with examples, once you’ve installed it go to Files->Examples->XT_Dac_Audio->PlayWav and you should see the code below;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "SoundData.h"; #include "XT_Dac_Audio.h"; XT_Wav_Class ForceWithYou(Force); // create an object of type XT_Wav_Class that is used by // the dac audio class (below), passing wav data as parameter. XT_DAC_Audio_Class DacAudio(25,0); // Create the main player class object. // Use GPIO 25, one of the 2 DAC pins and timer 0 void setup() { Serial.begin(115200); } void loop() { static uint32_t i=0; // simple counter to output if(ForceWithYou.Completed) // if completed playing, play again DacAudio.PlayWav(&ForceWithYou); // play the wav (pass the wav class object created at top of code Serial.println(i); // print out the value of i i++; // increment the value of i } |
In addition to this code you should see a second tab called SoundData.h which contains the actual wav sound data that we are going to use. You can ignore this for now. If you look at the code above we create two objects, one called DacAudio that creates an object that will handle any sound production through the DAC. We pass it the DAC GPIO pin and the system timer to use, there are four on the ESP32. We also need an object to hold the wav sound data, this is called ForceWithYou and is of the type XT_Wav_Class. To create this object we pass it the address of the wav sound data.
In the main loop we check if the sound ForceWithYou has completed (and at the first run it will be marked as completed) and if it has been we play it again so the sound loops again and again and again until you go insane! In addition to demonstrate the way the sound plays independently of your main loop code the main loop increments an integer and sends it to the serial monitor all the time that the sound is playing.
Adding your own sounds
I was going to write about how to do this but realised to put it in text would take an age (with screen shots and wordy descriptions) and not be very helpful, so if you haven;t already watched the supporting video at the top of this page then I highly advise you have a look as it explains how to add your own sounds. So that’s all for now, hope that’s been helpful and in the next article we’ll look at adding some additional commands to the DAC library to make making games sound easier without using up loads of memory with Wavs.
Previous Article – https://www.xtronical.com/basics/audio/dacs-on-esp32/