In this, the last episode on making our own wav player we are going to look at how we can mix multiple sounds together. If you haven’t seen the previous articles in this series then this is highly recommened as they contain circuit digrams and show the other aspects of the software as they’ve been created. You’ll find these other artivles on the basics menu under audio and I2S.
We are going to make the software play more than one wav sound at the same time. You might ask why, what’s the point in that? And from a playing music point of view there isn’t a point but I come from a gaming point of view where you often need background music and several different sounds all happening at once. The video below takes you through all that you need to know. Source code is available further down.
THEORY
Any waves, whether sound, electromagnetic or water, all interfere with each other if they mix. Look at these two waves. The middle line is the no energy or rest point of the wave, above is positive and below the line is negative. When two waves come together they simply add together. Any positives that match up get bigger and negatives that much up grow bigger too. If a positive meets with a negative then we’ll get a reduce wave.
As our sound waves are just digital representations of these waves we can just do the same, at the same point of 2 or more waves we just add the digital value for each of them together and repeat for all values going through to the I2S interface. So not actually a complex task.
CODE
I’ve again kept this code as simple as I could and it is just really proving the concept that it works. I would not normally write it like this as it is fairly inflexible, but that aside let’s have look.
EPILOGUE
And that’s it for this series of videos/articles, I hope this has been useful for helping you understand I2S and perhaps use it in your code. My next task is writing a new version of the DACAudio library for I2S, it will have all the functionality of the original but with higher quality sound and some extra features and it will be this library that I will continue with going forward, the old library will stay at it’s current version and I do not anticipate it being updated.
Till Next Time…
Thanks for a great tutorial series. I am interested in supporting the development of the I2S library for a project, could you get in touch?
Will do.
Thanks for the nice explanation. I have very basic doubt. Can we use Bluetooth received digital audio ( similar to a2dp sink) as source for I2S OR is there any other suggestion from you, which I can use to input the Bluetooth received signal to I2S.
In theory you can receive the data from Bluetooth, but obviously more coding required to achieve this. I can’t see a technical issue, perhaps someone may have already done this but I’ve not checked. Sorry for late reply, real life work has been very busy and I missed this comment.
These videos have been great. But I feel like I’m missing something basic. I want to be able to play a single sound based on an event in the code. But these seem much more about the streaming than the event driven playing. Any thoughts on just simply playing a specific wav/mp3 file in an isolated method? It doesn’t have to mix, just be discrete. Thanks.
Sorry for late reply, real life work has been very busy and I missed this comment. Just call the method to play the sound whenever your event occurs. I am working on a new library to replace my DACAudio library, which like this previous library will have plenty of examples to help you.
This is fantastic. No question at the moment – just a huge appreciation from me for your work. A new version sounds good as well, but i didn’t even test the old one. Will order parts and check it out!
Thanks for the feedback
@XTronica hey mate thanks for the vids.
I was wondering if you would try a directional mic project?
If you take a gander at https://invensense.tdk.com/wp-content/uploads/2015/02/Microphone-Array-Beamforming.pdf
https://www.analog.com/media/en/technical-documentation/application-notes/AN-1328.pdf
Is it possible to split the L/R stereo stream of x2 mics add a delay of the distance between invert one and mix back?
I think 48Khz works out approx 7mm so with wider spacing we can lower the SR.
I am thinking that is just the digital version of the above application notes and would an interesting project that reuses much of what you have done before.
Hi,
I think I answered this on the comments? Least I think I’ve had something similar come up. It’s all a matter of time, at the moment I’ve a full projects list. It’s one I will bare in mind though.
Many thanks for your work on the XT_DAC_Audio library. The capability to mix WAV sounds is great (I have made a donation)
I have started to rely on your library for the ESP32 audio project I am currently working on. The need for the project is :
– play simultaneously up to 15 WAV files
– duration of each WAV file could be up to 1 minute
CURRENT LIMITATION
Since current implementation of XT_DAC_Audio libray relies on PROGMEM, the number of audio files and duration which can be handled is rather limited, roughly 5 (short) files, 3 seconds duration each on an ESP32 Dev Module. Each (short) file is created with Audacity, mono, 8Khz, 8 bits
QUESTION
Can you please give some guidance on how the library could be extended to mix also WAV files READ FROM SD CARD ? If you think this is possible, I would like to do investigate this feature (and get back to you with results for visibility). Reading card from SD Card would get rid of the PROGMEM limitation. One difficulty is that because of the small amount of memory available on ESP32, all the WAV files cannot be loaded entirely in memory.
It seems the key part of code is “void XT_DAC_Audio_Class::FillBuffer()”, according to “XT_DAC_Audio.h” and “XT_DAC_Audio.cpp”
Thank you
Patrick
Sorry for the late reply (Christmas and work have been busy) and thank you for your kind donation. I’m working on the next version of DACAudio using I2S which will read from SD card. Pulling 15 from the card and mixing though may be a tough ask (might do it, not sure yet). Why do you need so many?
Thanks for reply. Glad to know that next version of XT_DAC_Audio should include capability to read files from SD Card, this is much appreciated
Regarding the number of simultaneous files to be read, 15 files with duration 1mn each is a target. More realistically, the capability to play 5 files simultaneously with a duration of 30s each is sufficient.
This will allow to play music chords, which are composed of several sounds. For instance chord Am is made of 3 sounds – A, C and E – hence the need to play simultaneously between 1 and 5 sounds.
Hi Patrick,
I see you are working on a similar project like me!
Have you tried the SDCardWavMixer.ino ???
In the descrition xtronical says “Simple example to demonstrate the fundementals of mixing WAV files (digitised sound) from an SD Card via the I2S interface of the ESP32….”
I thought this is exactly what we are looking for – isn’t it?
Have you tried this with more than two wavefiles playing simultanously from SD-card?
Please let me know how far you already got!
All the best.
Michael
Hello Michael,
Sorry for late reply, I just noticed your post today
Indeed I have tested “SDCardWavMixer.ino” 10 days ago, mixing 2 wav files, using example code and I2S audio amp . I found that quality is not satisfactory yet, there is some scratch and volume goes up and down. This is probably caused by the poor quality breadboard used, so I plan to do another test in the coming days with PCB, soldering and wrapping.
Hopefully the next version of audio Dac library could allow to play files from SD card using I2S, so we have to wait a little bit, I guess 🙂
Cheers
Patrick
Sound Quality of SDCardWavMixer.ino is much better with PCB, soldering and wrapping. Many thanks again to XTronical for this great piece of code 🙂
i got the hardware now. playing from sd-card works fine, but with the mixing example the wav files are played like double or triple speed …. this was the case when it was a mono file on the simple example. what else could be wrong?
how is your progress on your new library?
I’m not sure what your problem is with the speed thing. I’ve done some work on the library but it’ll be a couple of months before an initial release.
Thank you very much indeed for your genious work. I’m very interested in your ESP32 audio publications. Thank you for sharing these with us. I’ve just made a 50$-donation for supporting your work. Is it possible to mix up to 8 wavefiles with different starting time from SD-card? I want to trigger the waves by MIDI. Do you have any idea about “latency”? It would by fine if latency is below 20ms. Possible?
Thank you very much for your kind support!
Best regards Michael (from Austria)
Oh wow, I saw that donation come in and was overwhelmed. Sorry for the late reply to this. I’ve been swamped with real life work but have not got some time off work. I haven’t measured the latency however I suspect it will come in well under 10ms. I’m writing my own I2S library (based on my DACAudio work) and that will support mixing 8 and more sounds (as DacAudio does). Now DACAudio manages this easily because all sounds are stored on the ESP32 itself and obviously the access times are extremely fast compared to SD card. Although the new I2S library will support so many channels of sound I do not know if the SD card will keep up. But I will find out soon! I’m doing some work on it this week – not sure how far I will get though.
Again sorry for such a late reply!
Hi – Really helpful explanations thank you – learnt so much on your website
How can you use your latest library “XT_DAC_Audio.h” with an external DAC board?
Thank you in advance
If the board is I2S based then the performance isn’t good enough unfortunately. The data speed for I2S is too slow.
Thank you for the update
I saw your article on odysee re your library XT_IS2_AUDIO – which looks really amazing.
Are you going to publish XT_IS2_AUDIO at some point in the future?
Do you want a beta tester 🙂
Keep up the great work….
Regards
Jonathan