https://github.com/lefucjusz/helix-mp3-decoder
Fast and easy to use fixed-point MP3 decoder with dr_libs-style API. Based on libhelix-mp3.
https://github.com/lefucjusz/helix-mp3-decoder
audio decoding mp3 pico pico2 rp2040 rp2350
Last synced: 3 months ago
JSON representation
Fast and easy to use fixed-point MP3 decoder with dr_libs-style API. Based on libhelix-mp3.
- Host: GitHub
- URL: https://github.com/lefucjusz/helix-mp3-decoder
- Owner: Lefucjusz
- License: gpl-3.0
- Created: 2024-10-11T12:18:14.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2024-10-22T07:57:31.000Z (7 months ago)
- Last Synced: 2024-10-23T11:25:23.537Z (7 months ago)
- Topics: audio, decoding, mp3, pico, pico2, rp2040, rp2350
- Language: C
- Homepage:
- Size: 127 KB
- Stars: 3
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Helix-MP3-Decoder
Fast and easy to use fixed-point MP3 decoding library based on [libhelix-mp3](https://github.com/ultraembedded/libhelix-mp3) project. Wraps a rather complicated libhelix API into a much simpler dr_libs-style API to allow nearly plug-and-play substitution for [dr_mp3](https://github.com/mackron/dr_libs/blob/master/dr_mp3.h).
## Functionalities
* Pure fixed-point implementation
* Pure C and ASM code, no C++ required
* Support for MPEG-1 Layer 3
* Support for CBR and VBR
* Support for mono and stereo files (although the output is always 2-channel)
* Output in signed 16-bit PCM
* dr_libs-style API, easy to substitute for dr_mp3
* Enables to decode MP3 files in real-time on CPUs without FPU (tested on Pico and RISC-V core of Pico 2)
* ASM optimizations for ARM and RISC-V (easily extendable, see [assembly.h](src/libhelix/real/assembly.h))
* Fallback "unoptimized" routines enabling compilation for other platforms## Motivation
Main motivation for creating this library was to be able to run real-time MP3 playback on Hazard3 core of Pico2 board.
Typically the libraries I reach for when dealing with any audio decoding related task are [dr_libs](https://github.com/mackron/dr_libs). I've used them in a lot of different projects and find them to be a great piece of software, enabling to quickly add audio decoding capabilities to your device. They are incredibly versatile, but like everything, have their limitations. One of them is dr_mp3's heavy reliance on floating-point operations, which limits its usage to either CPUs with hardware FPU or CPUs powerful enough to perform software floating-point emulation fast enough to play MP3 files.
This was never a problem for me, as the MCU's I used always had an FPU... until I tried running it on Hazard3 core of Pico2 board. Despite writing the code in the most efficient way I could think of and compiling the project with the highest optimization level, it was unable to play MP3 without stuttering. Even overclocking that poor `RP2350` chip from 150MHz to 400(!)MHz wouldn't help. Why? Hazard3 core just happen to not have an FPU. At that moment I knew only a fixed-point decoder would save me... Of course I could just switch to ARM cores which would handle that task easily, but that was not the point at all :wink:
The only fixed-point MP3 decoder I could think of was libhelix-mp3, which I tried using some time ago, but never managed to get even past a compilation stage due to `unsupported platform` errors. Another issue was that its API is completely different (and in my opinion quite complicated to use) from the dr_libs API, for which I had already written a lot of code in many projects and I definitely didn't want to rewrite it. So I decided to spend some time to finally understand libhelix-mp3 and wrap it into a dr_libs-style API to be able to replace dr_mp3 with a mostly plug-and-play approach.
And so this library was born.
## API description
See [header file](src/helix_mp3.h) and [example source code](examples/decode/example_decode.c).
## How to use it in a project
The best way is probably to add this library as a submodule to your project:
```
git add submodule https://github.com/Lefucjusz/Helix-MP3-Decoder.git
```
then add library's directory to your main CMakeLists.txt:
```
add_subdirectory(Helix-MP3-Decoder)
```
After that you can link the library wherever it is needed:
```
target_link_libraries(
PRIVATE
helix_mp3
)
```## Examples
Minimal example of using the library can be found [here](examples/decode/example_decode.c). This simple utility decodes the provided MP3 file to raw PCM file.
The example of using the library with custom stream interface can be found [here](examples/decode_custom_io/example_decode_custom_io.c). This utility does exactly the same job as the minimal example, but using a custom stream interface.
To compile the examples, clone the repo and run the following commands:
```
mkdir -p build
cd build
cmake .. -DBUILD_EXAMPLES=1
make
```To use the compiled utilities, run:
```
./examples/decode/example_decode .mp3 .raw
```
or:
```
./examples/decode_custom_io/example_decode_custom_io .mp3 .raw
```After a successful run, you should get an output similar to:
```
./examples/decode/example_decode ~/test.mp3 output.rawDecoding '~/test.mp3' to 'output.raw'...
Reached EOF!
Done! Decoded 721152 frames, last frame sample rate: 44100Hz, bitrate: 32kbps
```
Output file contains raw 16-bit stereo PCM frames and can be played e.g. with Audacity via Import->Raw data option.