Hello there,
I am pretty new to Arduino programming and I want to play 16bit 22050kHz .wav Files from the SD-Card of an Adafruit Feather M0 Adalogger while the main code is running to read sensor Data and control LEDs.
I need the following features:
- playing 16bit 22050kHz .wav Files from folders
- keeping the main code running during playback and read sensor data
- functions to control continous loop, playback etc. (basically the same functions as in the TMRh20/TMRpcm library)
What is the best way implement my wishes into Arduino code? I have two ideas on the playback method but I am not sure if they will work:
- Using the onboard 10bit DAC and the Adafruit PAM8302
- Using I2S and the Adafruit MAX98357A
Regardless of my playback method I will need a library to make the playback independent from the main loop, or is there a relative easy way to implement some kind of "Multithreading" on a SAMD21 chip?
I do not want to use any additional brakout boards to my amplifier and sensor, because I am extremly resticted in space to put the finished project in.
It would be grat if someone cound give me some hints 
I read that you would prefer not to use any additional hardware, but I think if you look closely at this very small board, I think you will agree it is a good solution. DFPlayer Mini MP3 Player - DFRobot
I say it is a good solution, because it can take serial commands to play wave files stored on the local SD card on this module and not interfere with any ongoing data logging that might be happening on the SAM board. Also, it includes outputs for a small speaker, so has on-board low power audio amplifier.
Using a 10 bit DAC will produce a fairly low quality audio sound.
Paul - VK7KPA
Thanks for your reply.
I already know the DFPlayer
I did not yet decide to use it because I do not know if I can open and read textfiles stored on the SD card in it.
I am trying to build my own soundboard for my show fencing lightsaber, so I do not need super high quality audio 
I am using textfiles to save and modify the configuration of the lightsaber, like RGB colour profiles, so it is essential for me to be able to have acess to them.
Let me address the concurrency problem first - playing audio while other stuff happens in the foreground.
I just published this sketch: embedded-audio/8bit-sd-pwm at master · wildsparx/embedded-audio · GitHub which plays 8-bit audio - very similar to what you're trying to do.
You achieve concurrency by programming a timer interrupt on the chip at the sample rate. You may have to see what sample rates are practical on your chip, then remake the audio files at that sample rate. I used 32kHz, allowing 16kHz of bandwidth.
You need an audio buffer - a region of RAM to store samples. The foreground loop shovels data from the SD card to the buffer whenever there's room. The timer interrupt takes one sample at a time from the buffer.
The bigger the buffer, the more latency between firing and hearing a sound (in general). But a bigger buffer is less likely to have glitches. Any time the foreground loop fails to keep the buffer full, you get a glitch. That's why PCs normally use a very big buffer.
I used a double buffer, 2 x 512 bytes, so we can read from the SD card without touching the "live" half of the buffer.
ISR(TIMER2_OVF_vect) gets called 32k times/second.
Hi Pyrophorx,
I wanted to address the SD card/filesystem issues. Consider ditching the FAT filesystem and just using the raw card. The card is made of 512-byte blocks. You can assign certain blocks for your color profiles, etc. and others for audio.
BTW - a wav file is just PCM with a header - you might as well drop the header; no point in writing Arduino code to parse that, when you just want the PCM and already know the format.
We have to read SD cards via SPI - the "slow" interface. (The good interface needs a license agreement) I can get 384 kB/s - enough for 4 concurrent CD-quality streams. That's raw reads. Adding in the FAT filesystem adds overhead. Remember, it's not the average block read time, it's the max block read time that counts - you don't want glitches.
Maybe start by benchmarking your reads from the card, and computing the buffer size needed to avoid glitches (underruns). If it's more RAM than you can afford, or more latency than you want, consider bypassing FAT. Better to find this issue up front than hear glitches later.