Please note that a lot has changed since I published this Blog! Tought it might be possible to make this work again, you are advised to use the current API with this updated example!
The processing of files with the help of the ESP8266Audio is a little bit more involved. However it allows to process different audio file types from different sources. Please consult the project for further details.
Streaming of MP3 Files on a SD card
The Sketch
Here is the Arduino Sketch that you can use with an I2S audio source:
#include <SPI.h>
#include <SD.h>
#include "AudioFileSourceSD.h"
#include "AudioGeneratorMP3.h"
#include "AudioTools.h"
#include "AudioLibs/AudioESP8266.h"
#include "BluetoothA2DP.h"
const int sd_ss_pin = 5;
const char* fileName = "/audio.mp3";
BluetoothA2DPSource a2dp_source;
AudioFileSourceSD *file;
AudioGeneratorMP3 *mp3;
AudioOutputWithCallback *out;
// callback used by A2DP to provide the sound data
int32_t get_sound_data(Channels* data, int32_t len) {
return out == nullptr ? 0 : out->read(data, len);
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
audioLogger = &Serial;
// Setup Audio
file = new AudioFileSourceSD();
mp3 = new AudioGeneratorMP3();
out = new AudioOutputWithCallback(512,5);
// Open MP3 file and play it
SD.begin(sd_ss_pin);
if (file->open(fileName)) {
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.start("MyMusic", get_sound_data);
// start to play the file
mp3->begin(file, out);
Serial.printf("Playback of '%s' begins...\n", fileName);
} else {
Serial.println("Can't find .mp3 file");
}
}
// Arduino loop - repeated processing
void loop() {
if (mp3->isRunning()) {
if (!mp3->loop()) mp3->stop();
} else {
Serial.println("MP3 done");
delay(10000);
}
}
In this Sketch we use the ESP8266Audio library to read the audio.mp3 file from a SD drive. The output is pushed into a temporary buffer. The A2DP Callback then just consumes this buffered data. This is done with the help of the AudioOutputWithCallback class.
The Device
The SD module is connected with the help of the SPI bus
Pins
SD | ESP32 |
---|---|
VCC | 5V |
GND | GND |
CS | CS GP5 |
SCK | SCK GP18 |
MOSI | MOSI GP23 |
MISO | MISO GP19 |
5 Comments
dired · 17. August 2024 at 1:13
I tried to make this run “in 2024” successfully but ended up writing my own adapter:
class AudioOutputAdapter : public ::AudioOutput {
public:
AudioOutputAdapter(audio_tools::VolumeStream& volume) : volume_(volume) {}
virtual bool begin() override {
return true;
}
virtual bool ConsumeSample(int16_t sample[2]) override {
return volume_.write((uint8_t*)sample, 4) == 4;
}
virtual bool stop() override {
return true;
}
Maybe you could update the example, it was quite the nightmare to make it work. I also had to change scope resolution operators (“::”) in all imported header-files from esp8266audio because two “AudioOutput” variables exist, and esp8266audio is not properly namespaced like your lib.
Also had to specifiy the namespaces for AudioOutput in the ESP32-A2DP (3 files).
Not sure how feasible it is for you to provide a maintained example to combine the two libraries again! 🙂
Cheers
(not sure if
pschatzmann · 17. August 2024 at 1:27
There is no need to use the esp8266-audio library any more since the audio-tools can provide all the functionality.
Here is an even more powerfull example: https://github.com/pschatzmann/arduino-audio-tools/blob/main/examples/examples-communication/a2dp/player-sdfat-a2dp/player-sdfat-a2dp.ino
ps. You can avoid changing the esp8266-audio by importing these classes first and using the latest commits of the a2dp and audio-tools.
dired · 18. August 2024 at 2:48
Amazing and awesome! 😀
Thanks for helping me out with your c++ knowledge. I even had that in mind /done before in another sketch and somehow didn’t even try (properly).
Now I tried what you said and now it works without even touching the libs.
Thanks for providing current example for everyone to see!
What I actually wanted was to use the features of esp8266audio in your lib (or vice-versa, which turned out less feasible), which aren’t (“already” – maybe out of scope) there like MOD file support (this is what I did), but also SAM text-to-speech (which i will try also but I know you have even more fleshed out and diverse TTS already).
Since you say there is no need to use the esp8266-audio lib, does it mean there is no need anymore for AudioOutputWithCallback? There was no example in /examples/ (and online) for its usage except here, but then I also saw that you made a commit 2 months ago to AudioLibs/AudioESP8266.h, because of that I was convinced that there must be people using it / a fair use-case. But unfortunately wasn’t able to make it work as quickly as the own wrapper I posted.
After your text I’m also still a little confused on AudioOutputWithCallback ^^ I also saw your commit to it yesterday, thanks again. Maybe, if it’s used, with a little headstart I could try to write the example for everyone to see and make a push request (but right now I don’t even import AudioLibs/AudioESP8266.h).
Thanks again for the great lib (i know you hear that everyday, but rightfully so :D)
Anonymous · 27. September 2021 at 19:22
In your example, I had to replace “AudioOutputWithCallback.h” with “AudioESP8266.h”, otherwise AudioOutputWithCallback() can’t be fount
pschatzmann · 27. September 2021 at 20:54
Thanks for your feed back.