Chapter 31 Play SD card music

Note

The SD card chapter only applies to the ESP32 WROVER development board with an SD card slot on the back. If your ESP32 WROVER does not have an SD card slot on the back, please skip this chapter.

In the previous study, we have learned how to use the SD card, and then we will learn to play the music in the SD card.

Project 31.1 SDMMC Music

In this project, we will read an mp3 file from an SD card, decode it through ESP32, and use a speaker to play it.

Component List

ESP32 WROVER x1

Chapter01_00

USB cable x1

Chapter30_00

SDcard x1

Chapter30_02

Micro USB Wire x1

Chapter08_00

NPN transistorx1 (S8050)

Chapter07_02

Speaker

Chapter28_00

Diode x1

Chapter17_01

Resistor 1kΩ x1

Chapter07_03

Capacitor 10uF x1

Chapter28_01

Jumper F/M x4 Jumper F/F x2

Chapter24_08

Card reader x1 (random color)

Chapter30_01

(Not a USB flash drive.)

Circuit

Schematic diagram

Chapter31_00

Please note that before connecting the USB cable, please put the music into the SD card and insert the SD card into the card slot on the back of the ESP32.

Chapter31_01

Hardware connection

If you need any support, please feel free to contact us via: support@freenove.com

Chapter31_02

Sketch

How to install the library

In this project, we will use the ESP8266Audio.zip library to decode the audio files in the SD card, and then output the audio signal through GPIO. If you have not installed this library, please follow the steps below to install it.

Open arduino -> Sketch -> Include library -> Add .ZIP Library.

../../../_images/Chapter31_03.png

In the new pop-up window, select “Freenove_Ultimate_Starter_Kit_for_ESP32\C\Libraries\ESP8266Audio.zip”.

Then click “Open”.

../../../_images/Chapter31_04.png

Sketch_31.1_PlayMP3FromSD

We placed a folder called “music” in:

Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_31.1_PlayMP3FromSD

User needs to copy this folder to SD card.

../../../_images/Chapter31_05.png

Click upload.

../../../_images/Chapter31_06.png

Compile and upload the code to the ESP32 WROVER and open the serial monitor. ESP32 takes a few seconds to initialize the program. When you see the message below, it means that ESP32 has started parsing the mp3 in sd and started playing music through Pin.

../../../_images/Chapter31_07.png

The following is the program code:

 1#include <Arduino.h>
 2#include <WiFi.h>
 3#include "FS.h"
 4#include "SD_MMC.h"
 5#include "AudioFileSourceSD_MMC.h"
 6#include "AudioFileSourceID3.h"
 7#include "AudioGeneratorMP3.h"
 8#define IIS_ENABLE 0
 9
10#ifdef IIS_ENABLE
11#include "AudioOutputI2S.h"
12#else
13#include "AudioOutputI2SNoDAC.h"
14#endif
15
16#define SD_MMC_CMD 15 //Please do not modify it.
17#define SD_MMC_CLK 14 //Please do not modify it. 
18#define SD_MMC_D0  2  //Please do not modify it.
19#define I2S_BCLK   26
20#define I2S_DOUT   22
21#define I2S_LRC    25
22
23AudioGeneratorMP3 *mp3;
24AudioFileSourceID3 *id3;
25#ifdef IIS_ENABLE
26AudioOutputI2S *out;
27#else
28AudioOutputI2SNoDAC *out;
29#endif
30
31AudioFileSourceSD_MMC *file = NULL;
32
33// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc.
34void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
35{
36  (void)cbData;
37  Serial.printf("ID3 callback for: %s = '", type);
38
39  if (isUnicode) {
40    string += 2;
41  }
42
43  while (*string) {
44    char a = *(string++);
45    if (isUnicode) {
46      string++;
47    }
48    Serial.printf("%c", a);
49  }
50  Serial.printf("'\n");
51  Serial.flush();
52}
53
54void setup()
55{
56  WiFi.mode(WIFI_OFF); 
57  Serial.begin(115200);
58  delay(1000);
59  SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
60  if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
61      Serial.println("Card Mount Failed");
62      return;
63  }
64  Serial.printf("Sample MP3 playback begins...\n");
65
66  audioLogger = &Serial;
67  file = new AudioFileSourceSD_MMC("/music/01.mp3");
68  id3 = new AudioFileSourceID3(file);
69  id3->RegisterMetadataCB(MDCallback, (void*)"ID3TAG");
70  #ifdef IIS_ENABLE
71  out = new AudioOutputI2S();
72  #else
73  out = new AudioOutputI2SNoDAC();
74  #endif
75
76  out->SetPinout(I2S_BCLK,I2S_LRC,I2S_DOUT);//Set the audio output pin
77  out->SetGain(1.0);//Setting the Volume 0.1-3.9
78  mp3 = new AudioGeneratorMP3();
79  mp3->begin(id3, out);
80}
81
82void loop()
83{
84  if (mp3->isRunning()) {
85    if (!mp3->loop()) mp3->stop();
86  } else {
87    Serial.printf("MP3 done\n");
88    delay(1000);
89  }
90}

Add music decoding header files and SD card drive files.

If you want to use the circuit in 31.2, you just need to modify #define IIS_ENABLE 1.

 1#include <Arduino.h>
 2#include <WiFi.h>
 3#include "FS.h"
 4#include "SD_MMC.h"
 5#include "AudioFileSourceSD_MMC.h"
 6#include "AudioFileSourceID3.h"
 7#include "AudioGeneratorMP3.h"
 8#define IIS_ENABLE 0
 9
10#ifdef IIS_ENABLE
11#include "AudioOutputI2S.h"
12#else
13#include "AudioOutputI2SNoDAC.h"
14#endif

Define the drive pins for SD card. Note that the SD card driver pins cannot be modified.

1#define SD_MMC_CMD 15 //Please do not modify it.
2#define SD_MMC_CLK 14 //Please do not modify it. 
3#define SD_MMC_D0  2  //Please do not modify it.
4#define I2S_BCLK   26
5#define I2S_DOUT   22
6#define I2S_LRC    25

Apply for audio decoding class object.

1AudioGeneratorMP3 *mp3;
2AudioFileSourceID3 *id3;
3#ifdef IIS_ENABLE
4AudioOutputI2S *out;
5#else
6AudioOutputI2SNoDAC *out;
7#endif
8
9AudioFileSourceSD_MMC *file = NULL;

Set the audio file source and associate it with the decoder. Initialize the audio output pin and set the volume to 2.

 1audioLogger = &Serial;
 2file = new AudioFileSourceSD_MMC("/music/01.mp3");
 3id3 = new AudioFileSourceID3(file);
 4id3->RegisterMetadataCB(MDCallback, (void*)"ID3TAG");
 5#ifdef IIS_ENABLE
 6out = new AudioOutputI2S();
 7#else
 8out = new AudioOutputI2SNoDAC();
 9#endif
10
11out->SetPinout(I2S_BCLK,I2S_LRC,I2S_DOUT);//Set the audio output pin
12out->SetGain(1.0);//Setting the Volume 0.1-3.9
13mp3 = new AudioGeneratorMP3();
14mp3->begin(id3, out);

Determine whether the mp3 player is finished. If it is playing, continue playing. If it is finished, print a message.

1if (mp3->isRunning()) {
2  if (!mp3->loop()) mp3->stop();
3} else {
4  Serial.printf("MP3 done\n");
5  delay(1000);
6}

Project 31.2 SDMMC Music

In this project, we will read mp3 files from SD card, decode them through ESP32, and use Audio Converter & Amplifier module to transcode into stereo output.

Component List

ESP32 WROVER x1

Chapter01_00

USB cable x1

Chapter30_00

SDcard x1

Chapter30_02

Micro USB Wire x1

Chapter08_00

Audio Converter & Amplifier

Chapter29_00

Speaker

Chapter28_00

Jumper F/M x4

Jumper F/F x2

Chapter24_08

Card reader x1 (random color)

Chapter30_01

(Not a USB flash drive.)

Circuit

Schematic diagram

Chapter31_08

Please note that before connecting the USB cable, please put the music into the

SD card and insert the SD card into the card slot on the back of the ESP32.

Chapter31_09

Hardware connection

If you need any support, please feel free to contact us via: support@freenove.com

Chapter31_10

Sketch

How to install the library

In this project, we will use the ESP32-audioI2S.zip library to decode the audio files in the SD card, and then output the audio signal through IIS. If you have not installed this library, please follow the steps below to install it.

Open arduino -> Sketch -> Include library -> Add .ZIP Library.

../../../_images/Chapter31_11.png

In the new pop-up window, select “Freenove_Ultimate_Starter_Kit_for_ESP32\C\Libraries\ESP32-audioI2S.zip”.

Then click “Open”.

../../../_images/Chapter31_12.png

Sketch_31.2_SDMMC_Music

We placed a folder called “music” in:

Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_31.2_SDMMC_Music.

User needs to copy this folder to SD card.

../../../_images/Chapter31_13.png

Click Tools -> Partition Scheme, Select Huge APP……, Then click upload.

../../../_images/Chapter31_14.png

Compile and upload the code to the ESP32 WROVER and open the serial monitor. ESP32 takes a few seconds to initialize the program.

When you see the message below, it means that ESP32 has started parsing the mp3 in sd and started playing music through iis.

../../../_images/Chapter31_15.png

The following is the program code:

 1/**********************************************************************
 2  Filename    : SDMMC Music
 3  Description : Play music from the sd card.
 4  Auther      : www.freenove.com
 5  Modification: 2024/06/20
 6**********************************************************************/
 7#include "Arduino.h"
 8#include "Audio.h"
 9#include "FS.h"
10#include "SD_MMC.h"
11
12#define SD_MMC_CMD 15
13#define SD_MMC_CLK 14
14#define SD_MMC_D0  2
15#define I2S_BCLK   26
16#define I2S_DOUT   22
17#define I2S_LRC    25
18
19Audio audio;
20
21void setup() {
22  Serial.begin(115200);
23
24  SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
25  if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
26    Serial.println("Card Mount Failed");
27    return;
28  }
29  uint8_t cardType = SD_MMC.cardType();
30  if (cardType == CARD_NONE) {
31    Serial.println("No SD_MMC card attached");
32    return;
33  }
34  if (cardType == CARD_MMC) {
35    Serial.println("MMC");
36  } else if (cardType == CARD_SD) {
37    Serial.println("SDSC");
38  } else if (cardType == CARD_SDHC) {
39    Serial.println("SDHC");
40  } else {
41    Serial.println("UNKNOWN");
42  }
43  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
44  Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
45
46  audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
47  audio.setVolume(12);  // 0...21
48
49  audio.connecttoFS(SD_MMC, "/music/01.mp3");
50}
51
52void loop() {
53  audio.loop();
54  if (Serial.available()) {  // put streamURL in serial monitor
55    audio.stopSong();
56    String r = Serial.readString();
57    r.trim();
58    if (r.length() > 5) audio.connecttoFS(SD_MMC, r.c_str());
59    log_i("free heap=%i", ESP.getFreeHeap());
60  }
61}
62
63// optional
64void audio_info(const char *info) {
65  Serial.print("info        ");
66  Serial.println(info);
67}
68void audio_id3data(const char *info) {  //id3 metadata
69  Serial.print("id3data     ");
70  Serial.println(info);
71}
72void audio_eof_mp3(const char *info) {  //end of file
73  Serial.print("eof_mp3     ");
74  Serial.println(info);
75}
76void audio_showstation(const char *info) {
77  Serial.print("station     ");
78  Serial.println(info);
79}
80void audio_showstreamtitle(const char *info) {
81  Serial.print("streamtitle ");
82  Serial.println(info);
83}
84void audio_bitrate(const char *info) {
85  Serial.print("bitrate     ");
86  Serial.println(info);
87}
88void audio_commercial(const char *info) {  //duration in sec
89  Serial.print("commercial  ");
90  Serial.println(info);
91}
92void audio_icyurl(const char *info) {  //homepage
93  Serial.print("icyurl      ");
94  Serial.println(info);
95}
96void audio_lasthost(const char *info) {  //stream URL played
97  Serial.print("lasthost    ");
98  Serial.println(info);
99}

Add music decoding header files and SD card drive files.

1#include "Arduino.h"
2#include "Audio.h"
3#include "FS.h"
4#include "SD_MMC.h"

Define the drive pins for SD card and IIS. Note that the SD card driver pins cannot be modified, but the IIS drive pins can be modified.

1#define SD_MMC_CMD 15
2#define SD_MMC_CLK 14
3#define SD_MMC_D0  2
4#define I2S_BCLK   26
5#define I2S_DOUT   22
6#define I2S_LRC    25

Declare an audio decoding object, associate it with the pin, set the volume, and set the decoding object.

1Audio audio;
2......
3audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
4audio.setVolume(12);  // 0...21
5audio.connecttoFS(SD_MMC, "/music/Jingle Bells.mp3");

Play music until one piece of music finishes playing. If the serial port receives data, it will call the audio object to decode it after removing the spaces at the head and tail of the data.

1audio.loop();
2if (Serial.available()) {  // put streamURL in serial monitor
3  audio.stopSong();
4  String r = Serial.readString();
5  r.trim();
6  if (r.length() > 5) audio.connecttoFS(SD_MMC, r.c_str());
7  log_i("free heap=%i", ESP.getFreeHeap());
8}

In other words, if you want to switch the music in the SD card, you can directly input the song through the serial port.

1audio.loop();
2if (Serial.available()) {  // put streamURL in serial monitor
3  audio.stopSong();
4  String r = Serial.readString();
5  r.trim();
6  if (r.length() > 5) audio.connecttoFS(SD_MMC, r.c_str());
7  log_i("free heap=%i", ESP.getFreeHeap());
8}

The following functions are used to print the audio decoding information. If you do not want to see the decoding information in the serial port, you can directly comment out these functions.

1void audio_info(const char *info);
2void audio_id3data(const char *info);
3void audio_eof_mp3(const char *info);
4void audio_showstation(const char *info);
5void audio_showstreamtitle(const char *info);
6void audio_bitrate(const char *info);
7void audio_commercial(const char *info);
8void audio_icyurl(const char *info);
9void audio_lasthost(const char *info);