LAME is a open source implementation of a MP3 encoder. This project just reorganized the code to follow Arduino Library conventions, so that you can use it in Arduino and PlatformIO.
I have also added a simple Arduino style C++ API which allows to output the resulting MP3 via to a Arduino Stream or to receive it via a callback.
Here is an example Arduino sketch for encoding PCM data into MP3:
#include "MP3EncoderLAME.h"
#include <stdlib.h> // for rand
using namespace liblame;
void dataCallback(uint8_t *mp3_data, size_t len) {
Serial.print("mp3 generated with ");
Serial.print(len);
Serial.println(" bytes");
}
MP3EncoderLAME mp3(dataCallback);
AudioInfo info;
int16_t buffer[512];
void setup() {
Serial.begin(115200);
info.channels = 1;
info.sample_rate = 44100;
mp3.begin(info);
Serial.println("writing...");
}
void loop() {
Serial.println("writing 512 samples of random data");
for (int j=0;j<512;j++){
buffer[j] = (rand() % 100) - 50;
}
mp3.write(buffer, 512*sizeof(int16_t));
}
In Arduino, you can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with
cd ~/Documents/Arduino/libraries
git clone pschatzmann/arduino-liblame.git
This project can also be built and executed on your desktop with cmake:
cd arduino-liblame
mkdir build
cd build
cmake ..
make
- The Class Documentation can be found here
- You can also find some more information in my dedicated Blog.
- I also suggest that you have a look at my overview Blog
I recommend to use this library together with my Arduino Audio Tools. This is just one of many codecs that I have collected so far: Further details can be found in the Encoding and Decoding Wiki of the Audio Tools.
This library requires quite a lot of RAM and it should work if you just use this decoder w/o any additional functionality that requires additional RAM. If you want to use e.g. WIFI together with this library you might not have enough RAM: Fortunately this library supports PSRAM so if you activate PSRAM you should have more then enough headroom...
The initial restructured code was working prefectly with my Arduino Simulator on the desktop, but as soon I as I deployed it on an ESP32 it was crashing because of different reasons:
- The memory structures were partly too big
- Long arrays were allocated on the stack
So I needed to adjust the original code quite a bit. You can activate some micro processor specific functionaitly in config.h.
// use dynamically precalculated log table
#define USE_FAST_LOG 0
// use precalculated log table as const -> in the ESP32 this will end up in flash memory
#define USE_FAST_LOG_CONST 1
// Avoid big memory allocations in replaygain_data: with PSRAM this can be 0
#define USE_MEMORY_HACK 1
// If you know the encoder will be used in a single threaded environment, you can use this hack to just
// recycle the memory. This will prevent memory fragmentation. Only use this if you are sure that the
// encoder will be called from a single thread.
#define USE_STACK_HACK_RECYCLE_ALLOCATION_SINGLE_THREADED 1
// If the device is ESP32 and ESP_PSRAM_ENABLE_LIMIT is > 0, then the ESP32 will
// be configured to use allocate any allocation above ESP_PSRAM_ENABLE_LIMIT using
// psram, rather than scarce main memory.
#define ESP_PSRAM_ENABLE_LIMIT 1024
// Not all microcontroller support vararg methods: alternative impelemtation of logging using the preprocessor
#define USE_LOGGING_HACK 1
// Print debug and trace messages
#define USE_DEBUG 0
// Print memory allocations and frees
#define USE_DEBUG_ALLOC 0
// The stack on microcontrollers is very limited - use the heap for big arrays instead of the stack!
#define USE_STACK_HACK 1
ESP32 Arduino 2.0.x Releases are using a lot of static memory and you will need to set USE_MEMORY_HACK to 0 to be able to compile this library.