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

sd

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

Source Code

Both the project and the example can be found on Github.


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.

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *