Skip to content

Commit 16f175d

Browse files
committed
Arduino Support
1 parent afb604c commit 16f175d

File tree

4 files changed

+330
-299
lines changed

4 files changed

+330
-299
lines changed

README.md

Lines changed: 8 additions & 299 deletions
Original file line numberDiff line numberDiff line change
@@ -1,310 +1,19 @@
1-
minimp3
2-
==========
3-
4-
[![Build Status](https://travis-ci.org/lieff/minimp3.svg)](https://travis-ci.org/lieff/minimp3)
5-
<a href="https://scan.coverity.com/projects/lieff-minimp3">
6-
<img alt="Coverity Scan Build Status"
7-
src="https://scan.coverity.com/projects/14844/badge.svg"/>
8-
</a>
9-
[![codecov](https://codecov.io/gh/lieff/minimp3/branch/master/graph/badge.svg)](https://codecov.io/gh/lieff/minimp3)
1+
# arduino-minimp3
102

113
Minimalistic, single-header library for decoding MP3. minimp3 is designed to be
12-
small, fast (with SSE and NEON support), and accurate (ISO conformant). You can
13-
find a rough benchmark below, measured using ``perf`` on an i7-6700K, IO
14-
included, no CPU heat to address speedstep:
15-
16-
| Vector | Hz | Samples| Sec | Clockticks | Clockticks per second | PSNR | Max diff |
17-
| ----------- | ----- | ------ | ------ | --------- | ------ | ------ | - |
18-
|compl.bit | 48000 | 248832 | 5.184 | 14306684 | 2.759M | 124.22 | 1 |
19-
|he_32khz.bit | 32000 | 172800 | 5.4 | 8426158 | 1.560M | 139.67 | 1 |
20-
|he_44khz.bit | 44100 | 472320 | 10.710 | 21296300 | 1.988M | 144.04 | 1 |
21-
|he_48khz.bit | 48000 | 172800 | 3.6 | 8453846 | 2.348M | 139.67 | 1 |
22-
|hecommon.bit | 44100 | 69120 | 1.567 | 3169715 | 2.022M | 133.93 | 1 |
23-
|he_free.bit | 44100 | 156672 | 3.552 | 5798418 | 1.632M | 137.48 | 1 |
24-
|he_mode.bit | 44100 | 262656 | 5.955 | 9882314 | 1.659M | 118.00 | 1 |
25-
|si.bit | 44100 | 135936 | 3.082 | 7170520 | 2.326M | 120.30 | 1 |
26-
|si_block.bit | 44100 | 73728 | 1.671 | 4233136 | 2.533M | 125.18 | 1 |
27-
|si_huff.bit | 44100 | 86400 | 1.959 | 4785322 | 2.442M | 107.98 | 1 |
28-
|sin1k0db.bit | 44100 | 725760 | 16.457 | 24842977 | 1.509M | 111.03 | 1 |
29-
30-
Conformance test passed on all vectors (PSNR > 96db).
31-
32-
## Comparison with keyj's [minimp3](https://keyj.emphy.de/minimp3/)
33-
34-
Comparison by features:
35-
36-
| Keyj minimp3 | Current |
37-
| ------------ | ------- |
38-
| Fixed point | Floating point |
39-
| source: 84kb | 70kb |
40-
| binary: 34kb (20kb compressed) | 30kb (20kb) |
41-
| no vector opts | SSE/NEON intrinsics |
42-
| no free format | free format support |
43-
44-
Below, you can find the benchmark and conformance test for keyj's minimp3:
45-
46-
47-
| Vector | Hz | Samples| Sec | Clockticks | Clockticks per second | PSNR | Max diff |
48-
| ----------- | ----- | ------ | ------ | --------- | ------ | ----- | - |
49-
|compl.bit | 48000 | 248832 | 5.184 | 31849373 | 6.143M | 71.50 | 41 |
50-
|he_32khz.bit | 32000 | 172800 | 5.4 | 26302319 | 4.870M | 71.63 | 24 |
51-
|he_44khz.bit | 44100 | 472320 | 10.710 | 41628861 | 3.886M | 71.63 | 24 |
52-
|he_48khz.bit | 48000 | 172800 | 3.6 | 25899527 | 7.194M | 71.63 | 24 |
53-
|hecommon.bit | 44100 | 69120 | 1.567 | 20437779 | 13.039M | 71.58 | 25 |
54-
|he_free.bit | 44100 | 0 | 0 | - | - | - | - |
55-
|he_mode.bit | 44100 | 262656 | 5.955 | 30988984 | 5.203M | 71.78 | 27 |
56-
|si.bit | 44100 | 135936 | 3.082 | 24096223 | 7.817M | 72.35 | 36 |
57-
|si_block.bit | 44100 | 73728 | 1.671 | 20722017 | 12.394M | 71.84 | 26 |
58-
|si_huff.bit | 44100 | 86400 | 1.959 | 21121376 | 10.780M | 27.80 | 65535 |
59-
|sin1k0db.bit | 44100 | 730368 | 16.561 | 55569636 | 3.355M | 0.15 | 58814 |
60-
61-
Keyj minimp3 conformance test fails on all vectors (PSNR < 96db), and free
62-
format is unsupported. This caused some problems when it was used
63-
[here](https://github.com/lieff/lvg), and was the main motivation for this work.
64-
65-
## Usage
66-
67-
First, we need to initialize the decoder structure:
68-
69-
```c
70-
//#define MINIMP3_ONLY_MP3
71-
//#define MINIMP3_ONLY_SIMD
72-
//#define MINIMP3_NO_SIMD
73-
//#define MINIMP3_NONSTANDARD_BUT_LOGICAL
74-
//#define MINIMP3_FLOAT_OUTPUT
75-
#define MINIMP3_IMPLEMENTATION
76-
#include "minimp3.h"
77-
...
78-
static mp3dec_t mp3d;
79-
mp3dec_init(&mp3d);
80-
```
81-
82-
Note that you must define ``MINIMP3_IMPLEMENTATION`` in exactly one source file.
83-
You can ``#include`` ``minimp3.h`` in as many files as you like.
84-
Also you can use ``MINIMP3_ONLY_MP3`` define to strip MP1/MP2 decoding code.
85-
MINIMP3_ONLY_SIMD define controls generic (non SSE/NEON) code generation (always enabled on x64/arm64 targets).
86-
In case you do not want any platform-specific SIMD optimizations, you can define ``MINIMP3_NO_SIMD``.
87-
MINIMP3_NONSTANDARD_BUT_LOGICAL define saves some code bytes, and enforces non-standard but logical behaviour of mono-stereo transition (rare case).
88-
MINIMP3_FLOAT_OUTPUT makes ``mp3dec_decode_frame()`` output to be float instead of short and additional function mp3dec_f32_to_s16 will be available for float->short conversion if needed.
89-
90-
Then. we decode the input stream frame-by-frame:
91-
92-
```c
93-
/*typedef struct
94-
{
95-
int frame_bytes;
96-
int channels;
97-
int hz;
98-
int layer;
99-
int bitrate_kbps;
100-
} mp3dec_frame_info_t;*/
101-
mp3dec_frame_info_t info;
102-
short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
103-
/*unsigned char *input_buf; - input byte stream*/
104-
samples = mp3dec_decode_frame(&mp3d, input_buf, buf_size, pcm, &info);
105-
```
106-
107-
The ``mp3dec_decode_frame()`` function decodes one full MP3 frame from the
108-
input buffer, which must be large enough to hold one full frame.
109-
110-
The decoder will analyze the input buffer to properly sync with the MP3 stream,
111-
and will skip ID3 data, as well as any data which is not valid. Short buffers
112-
may cause false sync and can produce 'squealing' artefacts. The bigger the size
113-
of the input buffer, the more reliable the sync procedure. We recommend having
114-
as many as 10 consecutive MP3 frames (~16KB) in the input buffer at a time.
115-
116-
At end of stream just pass rest of the buffer, sync procedure should work even
117-
with just 1 frame in stream (except for free format and garbage at the end can
118-
mess things up, so id3v1 and ape tags must be removed first).
119-
120-
For free format there minimum 3 frames needed to do proper sync: 2 frames to
121-
detect frame length and 1 next frame to check detect is good.
122-
123-
The size of the consumed MP3 data is returned in the ``mp3dec_frame_info_t``
124-
field of the ``frame_bytes`` struct; you must remove the data corresponding to
125-
the ``frame_bytes`` field from the input buffer before the next decoder
126-
invocation.
127-
128-
The decoding function returns the number of decoded samples. The following cases
129-
are possible:
4+
small, fast (with SSE and NEON support), and accurate (ISO conformant). Further information can be found in the [oringal readme](README.original).
1305

131-
- **0:** No MP3 data was found in the input buffer
132-
- **384:** Layer 1
133-
- **576:** MPEG 2 Layer 3
134-
- **1152:** Otherwise
6+
I have extended the project so that it can be used as Arduino library.
1357

136-
The following is a description of the possible combinations of the number of
137-
samples and ``frame_bytes`` field values:
8+
### Installation in Arduino
1389

139-
- More than 0 samples and ``frame_bytes > 0``: Succesful decode
140-
- 0 samples and ``frame_bytes > 0``: The decoder skipped ID3 or invalid data
141-
- 0 samples and ``frame_bytes == 0``: Insufficient data
10+
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
14211

143-
If ``frame_bytes == 0``, the other fields may be uninitialized or unchanged; if
144-
``frame_bytes != 0``, the other fields are available. The application may call
145-
``mp3dec_init()`` when changing decode position, but this is not necessary.
146-
147-
As a special case, the decoder supports already split MP3 streams (for example,
148-
after doing an MP4 demux). In this case, the input buffer must contain _exactly
149-
one_ non-free-format frame.
150-
151-
## Seeking
152-
153-
You can seek to any byte in the stream and call ``mp3dec_decode_frame``; this
154-
will work in almost all cases, but is not completely guaranteed. Probablility of
155-
sync procedure failure lowers when MAX_FRAME_SYNC_MATCHES value grows. Default
156-
MAX_FRAME_SYNC_MATCHES=10 and probablility of sync failure should be very low.
157-
If granule data is accidentally detected as a valid MP3 header, short audio artefacting is
158-
possible.
159-
160-
High-level mp3dec_ex_seek function supports precise seek to sample (MP3D_SEEK_TO_SAMPLE)
161-
using index and binary search.
162-
163-
## Track length detect
164-
165-
If the file is known to be cbr, then all frames have equal size and
166-
lack ID3 tags, which allows us to decode the first frame and calculate all frame
167-
positions as ``frame_bytes * N``. However, because of padding, frames can differ
168-
in size even in this case.
169-
170-
In general case whole stream scan is needed to calculate it's length. Scan can be
171-
omitted if vbr tag is present (added by encoders like lame and ffmpeg), which contains
172-
length info. High-level functions automatically use the vbr tag if present.
173-
174-
## High-level API
175-
176-
If you need only decode file/buffer or use precise seek, you can use optional high-level API.
177-
Just ``#include`` ``minimp3_ex.h`` instead and use following additional functions:
178-
179-
```c
180-
#define MP3D_SEEK_TO_BYTE 0
181-
#define MP3D_SEEK_TO_SAMPLE 1
182-
183-
#define MINIMP3_PREDECODE_FRAMES 2 /* frames to pre-decode and skip after seek (to fill internal structures) */
184-
/*#define MINIMP3_SEEK_IDX_LINEAR_SEARCH*/ /* define to use linear index search instead of binary search on seek */
185-
#define MINIMP3_IO_SIZE (128*1024) /* io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE */
186-
#define MINIMP3_BUF_SIZE (16*1024) /* buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case */
187-
#define MINIMP3_ENABLE_RING 0 /* enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
188-
189-
#define MP3D_E_MEMORY -1
190-
#define MP3D_E_IOERROR -2
191-
192-
typedef struct
193-
{
194-
mp3d_sample_t *buffer;
195-
size_t samples; /* channels included, byte size = samples*sizeof(mp3d_sample_t) */
196-
int channels, hz, layer, avg_bitrate_kbps;
197-
} mp3dec_file_info_t;
198-
199-
typedef size_t (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);
200-
typedef int (*MP3D_SEEK_CB)(uint64_t position, void *user_data);
201-
202-
typedef struct
203-
{
204-
MP3D_READ_CB read;
205-
void *read_data;
206-
MP3D_SEEK_CB seek;
207-
void *seek_data;
208-
} mp3dec_io_t;
209-
210-
typedef struct
211-
{
212-
uint64_t samples;
213-
mp3dec_frame_info_t info;
214-
int last_error;
215-
...
216-
} mp3dec_ex_t;
217-
218-
typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, uint64_t offset, mp3dec_frame_info_t *info);
219-
typedef int (*MP3D_PROGRESS_CB)(void *user_data, size_t file_size, uint64_t offset, mp3dec_frame_info_t *info);
220-
221-
/* decode whole buffer block */
222-
int mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
223-
int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
224-
/* iterate through frames */
225-
int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
226-
int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
227-
/* streaming decoder with seeking capability */
228-
int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method);
229-
int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method);
230-
void mp3dec_ex_close(mp3dec_ex_t *dec);
231-
int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
232-
size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples);
233-
#ifndef MINIMP3_NO_STDIO
234-
/* stdio versions of file load, iterate and stream */
235-
int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
236-
int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
237-
int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method);
238-
#ifdef _WIN32
239-
int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
240-
int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data);
241-
int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int seek_method);
242-
#endif
243-
#endif
24412
```
245-
246-
Use MINIMP3_NO_STDIO define to exclude STDIO functions.
247-
MINIMP3_ALLOW_MONO_STEREO_TRANSITION allows mixing mono and stereo in same file.
248-
In that case ``mp3dec_frame_info_t->channels = 0`` is reported on such files and correct channels number passed to progress_cb callback for each frame in mp3dec_frame_info_t structure.
249-
MP3D_PROGRESS_CB is optional and can be NULL, example of file decoding:
250-
251-
```c
252-
mp3dec_t mp3d;
253-
mp3dec_file_info_t info;
254-
if (mp3dec_load(&mp3d, input_file_name, &info, NULL, NULL))
255-
{
256-
/* error */
257-
}
258-
/* mp3dec_file_info_t contains decoded samples and info,
259-
use free(info.buffer) to deallocate samples */
260-
```
261-
262-
Example of file decoding with seek capability:
263-
264-
```c
265-
mp3dec_ex_t dec;
266-
if (mp3dec_ex_open(&dec, input_file_name, MP3D_SEEK_TO_SAMPLE))
267-
{
268-
/* error */
269-
}
270-
/* dec.samples, dec.info.hz, dec.info.layer, dec.info.channels should be filled */
271-
if (mp3dec_ex_seek(&dec, position))
272-
{
273-
/* error */
274-
}
275-
mp3d_sample_t *buffer = malloc(dec.samples*sizeof(mp3d_sample_t));
276-
size_t readed = mp3dec_ex_read(&dec, buffer, dec.samples);
277-
if (readed != dec.samples) /* normal eof or error condition */
278-
{
279-
if (dec.last_error)
280-
{
281-
/* error */
282-
}
283-
}
13+
cd ~/Documents/Arduino/libraries
14+
git clone pschatzmann/arduino-minimp3.git
28415
```
28516

286-
## Bindings
287-
288-
* https://github.com/tosone/minimp3 - go bindings
289-
* https://github.com/notviri/rmp3 - rust `no_std` bindings which don't allocate.
290-
* https://github.com/germangb/minimp3-rs - rust bindings
291-
* https://github.com/johangu/node-minimp3 - NodeJS bindings
292-
* https://github.com/pyminimp3/pyminimp3 - python bindings
293-
* https://github.com/bashi/minimp3-wasm - wasm bindings
294-
* https://github.com/DasZiesel/minimp3-delphi - delphi bindings
295-
* https://github.com/mgeier/minimp3_ex-sys - low-level rust bindings to `minimp3_ex`
17+
I recommend to use git because you can easily update to the latest version just by executing the ```git pull``` command in the project folder.
29618

297-
## Interesting links
29819

299-
* https://keyj.emphy.de/minimp3/
300-
* https://github.com/technosaurus/PDMP3
301-
* https://github.com/technosaurus/PDMP2
302-
* https://github.com/packjpg/packMP3
303-
* https://sites.google.com/a/kmlager.com/www/projects
304-
* https://sourceforge.net/projects/mp3dec/
305-
* http://blog.bjrn.se/2008/10/lets-build-mp3-decoder.html
306-
* http://www.mp3-converter.com/mp3codec/
307-
* http://www.multiweb.cz/twoinches/mp3inside.htm
308-
* https://www.mp3-tech.org/
309-
* https://id3.org/mp3Frame
310-
* https://www.datavoyage.com/mpgscript/mpeghdr.htm

0 commit comments

Comments
 (0)