|
1 |
| -minimp3 |
2 |
| -========== |
3 |
| - |
4 |
| -[](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 |
| -[](https://codecov.io/gh/lieff/minimp3) |
| 1 | +# arduino-minimp3 |
10 | 2 |
|
11 | 3 | 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). |
130 | 5 |
|
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. |
135 | 7 |
|
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 |
138 | 9 |
|
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 |
142 | 11 |
|
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 |
244 | 12 | ```
|
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 |
284 | 15 | ```
|
285 | 16 |
|
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. |
296 | 18 |
|
297 |
| -## Interesting links |
298 | 19 |
|
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