Arduino Library for MP3 Decoding

by the2ndTierney in Circuits > Arduino

5277 Views, 5 Favorites, 0 Comments

Arduino Library for MP3 Decoding

MP3_logo.png
waveform.PNG

Due to the increased prevalence of speedy microcontrollers such as the ESP32 and the ARM M series MP3 decoding is no longer required to be done by specialist hardware. The decoding can now be done in software.

There's a great library available from earlephilhower that shows how to decode a wide variety of audio files and play them on ESP microcontrollers. Inspired by this I adapted some of the code to create a modular method of reading MP3 files on microcontrollers.

My hope is that this method will be generic enough for use on any fast enough microcontroller (not just an ESP32 board) but as of now I have only tested on an ESP32.

Supplies

As I said before, I hope this method will work for any fast microcontroller, but it may not. Therefore to replicate my results you will need:

Laying Out the Breadboard

afterfocus_1595955162195.jpg

Place ESP32 and SD card breakout on the breadboard.

Wiring the SD Card

20200728_180255.jpg

The SD card connections (ESP32 --> SD breakout) are as follows:

GND --> GND

3v3 --> VDD

23 --> DI (MOSI)

19 --> DO (MISO)

18 --> SCLK

5 --> CS

Please note that these connections will be different if you are using a different microcontroller.

The Software Libraries

if you don't have the ESP-IDF installed head over to their website and install it.

Then install the microdecoder library. You can do this by downloading the repository and placing it in your Arduino Libraries folder. The microdecoder library currently supports .wav and .mp3 files.

Regardless of the format, there are a few common methods associated with each class and they are covered in the code below. These include getting some the files metadata and printing it to the serial monitor.

#include "SD.h"                                   // input
#include "mp3.h"                                  // decoder
#include "pcm.h"                                  // raw audio data container

mp3 MP3;

void setup() {
  Serial.begin(115200);                           // Setup Serial
  SD.begin();                                     // Setup SD connection
 
  File file = SD.open("/cc.mp3");                 // Open an MP3 File
  
  MP3.begin(file);                                // tell  the MP3 class what file to process
  MP3.getMetadata();                              // get the metdadata 
  
  Serial.print("Bits per Sample: ");
  Serial.println(MP3.bitsPerSample);             // print bits per sample
  Serial.print("Sample Rate: "); 
  Serial.println(MP3.Fs);                        // and sample rate
  
  
}

void loop() {
}

Plot MP3 Data on the Serial Monitor

waveform.PNG

With the code below you can plot some audio data on the Serial monitor. This will be very slow but will show you how to use the MP3 library. It also downsamples the data by a factor of 16 so that when the data is plotted it looks like an audio waveform. This code is taken from the example SPI_MP3_Serial.ino that comes with the microdecoder library. Of course, moving forward you will want to play this audio data somehow but that's the topic of a different instructable.

#include "SD.h"                                   // input
#include "mp3.h"                                  // decoder

mp3 MP3;                                          // MP3 Class
pcm audio;                                        // raw audio data

void setup() {
  Serial.begin(115200);                           // Setup Serial
  SD.begin();                                     // Setup SD connection
 
  File file = SD.open("/cc.mp3");                 // Open an MP3 File
  
  MP3.begin(file);                                // Pass file to MP3 class
}

void loop() {
  audio = MP3.decode();                          // Decode audio data into pcm class
  
  /* there are 32 samples in audio.interleaved (16 left and 16 right)
   *  but we are only going to plot the first data point in each channel.
   *  This effectively downamples the data by  a factor of 16 (for
   *   viewing the waveform only)
   */
  
  Serial.print(audio.interleaved[0]);            // left channel
  Serial.print(" ");                      
  Serial.println(audio.interleaved[1]);         // right channel  
}