Skip to content

Commit e583f50

Browse files
committed
Arduino support: reduce stack required
1 parent 16f175d commit e583f50

File tree

2 files changed

+75
-52
lines changed

2 files changed

+75
-52
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# arduino-minimp3
22

3-
Minimalistic, single-header library for decoding MP3. minimp3 is designed to be
4-
small, fast (with SSE and NEON support), and accurate (ISO conformant). Further information can be found in the [oringal readme](README.original).
3+
Minimalistic, single-header library for decoding MP3. minimp3 is designed to be small, fast (with SSE and NEON support), and accurate (ISO conformant). Further information can be found in the [oringal readme](README.original).
4+
5+
I have extended the project, so that it can be used as Arduino library. The result however is not very convincing: The decoder is too slow (e.g. on an ESP32) to decode any audio with a rate >= 32000 samples per second and the audio quality is quite poor.
56

6-
I have extended the project so that it can be used as Arduino library.
77

88
### Installation in Arduino
99

minimp3.h

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,49 @@
99
#include <stdint.h>
1010

1111
#define MINIMP3_MAX_SAMPLES_PER_FRAME (1152*2)
12+
#define MAX_BITRESERVOIR_BYTES 511
13+
#define MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
14+
#define MAX_L3_FRAME_PAYLOAD_BYTES MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
15+
16+
#ifndef MINIMP3_STACK_OPT
17+
#define MINIMP3_STACK_OPT 1
18+
#endif
19+
20+
typedef struct
21+
{
22+
const uint8_t *buf;
23+
int pos, limit;
24+
} bs_t;
25+
26+
typedef struct
27+
{
28+
float scf[3*64];
29+
uint8_t total_bands, stereo_bands, bitalloc[64], scfcod[64];
30+
} L12_scale_info;
31+
32+
typedef struct
33+
{
34+
uint8_t tab_offset, code_tab_width, band_count;
35+
} L12_subband_alloc_t;
36+
37+
typedef struct
38+
{
39+
const uint8_t *sfbtab;
40+
uint16_t part_23_length, big_values, scalefac_compress;
41+
uint8_t global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
42+
uint8_t table_select[3], region_count[3], subblock_gain[3];
43+
uint8_t preflag, scalefac_scale, count1_table, scfsi;
44+
} L3_gr_info_t;
45+
46+
47+
typedef struct
48+
{
49+
bs_t bs;
50+
uint8_t maindata[MAX_BITRESERVOIR_BYTES + MAX_L3_FRAME_PAYLOAD_BYTES];
51+
L3_gr_info_t gr_info[4];
52+
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
53+
uint8_t ist_pos[2][39];
54+
} mp3dec_scratch_t;
1255

1356
typedef struct
1457
{
@@ -20,6 +63,12 @@ typedef struct
2063
float mdct_overlap[2][9*32], qmf_state[15*2*32];
2164
int reserv, free_format_bytes;
2265
unsigned char header[4], reserv_buf[511];
66+
#if MINIMP3_STACK_OPT
67+
mp3dec_scratch_t scratch;
68+
# ifndef MINIMP3_ONLY_MP3
69+
L12_scale_info sci;
70+
# endif
71+
#endif
2372
} mp3dec_t;
2473

2574
#ifdef __cplusplus
@@ -46,14 +95,11 @@ int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_s
4695
#include <stdlib.h>
4796
#include <string.h>
4897

49-
#define MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
5098
#ifndef MAX_FRAME_SYNC_MATCHES
5199
#define MAX_FRAME_SYNC_MATCHES 10
52100
#endif /* MAX_FRAME_SYNC_MATCHES */
53101

54-
#define MAX_L3_FRAME_PAYLOAD_BYTES MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
55102

56-
#define MAX_BITRESERVOIR_BYTES 511
57103
#define SHORT_BLOCK_TYPE 2
58104
#define STOP_BLOCK_TYPE 3
59105
#define MODE_MONO 3
@@ -203,40 +249,6 @@ static __inline__ __attribute__((always_inline)) int32_t minimp3_clip_int16_arm(
203249
#define HAVE_ARMV6 0
204250
#endif
205251

206-
typedef struct
207-
{
208-
const uint8_t *buf;
209-
int pos, limit;
210-
} bs_t;
211-
212-
typedef struct
213-
{
214-
float scf[3*64];
215-
uint8_t total_bands, stereo_bands, bitalloc[64], scfcod[64];
216-
} L12_scale_info;
217-
218-
typedef struct
219-
{
220-
uint8_t tab_offset, code_tab_width, band_count;
221-
} L12_subband_alloc_t;
222-
223-
typedef struct
224-
{
225-
const uint8_t *sfbtab;
226-
uint16_t part_23_length, big_values, scalefac_compress;
227-
uint8_t global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
228-
uint8_t table_select[3], region_count[3], subblock_gain[3];
229-
uint8_t preflag, scalefac_scale, count1_table, scfsi;
230-
} L3_gr_info_t;
231-
232-
typedef struct
233-
{
234-
bs_t bs;
235-
uint8_t maindata[MAX_BITRESERVOIR_BYTES + MAX_L3_FRAME_PAYLOAD_BYTES];
236-
L3_gr_info_t gr_info[4];
237-
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
238-
uint8_t ist_pos[2][39];
239-
} mp3dec_scratch_t;
240252

241253
static void bs_init(bs_t *bs, const uint8_t *data, int bytes)
242254
{
@@ -1715,7 +1727,13 @@ int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_s
17151727
int i = 0, igr, frame_size = 0, success = 1;
17161728
const uint8_t *hdr;
17171729
bs_t bs_frame[1];
1730+
#if MINIMP3_STACK_OPT
1731+
mp3dec_scratch_t *p_scratch = &(dec->scratch);
1732+
memset(p_scratch,0,sizeof(mp3dec_scratch_t));
1733+
#else
17181734
mp3dec_scratch_t scratch;
1735+
mp3dec_scratch_t *p_scratch = &scratch;
1736+
#endif
17191737

17201738
if (mp3_bytes > 4 && dec->header[0] == 0xff && hdr_compare(dec->header, mp3))
17211739
{
@@ -1758,40 +1776,45 @@ int mp3dec_decode_frame(mp3dec_t *dec, const uint8_t *mp3, int mp3_bytes, mp3d_s
17581776

17591777
if (info->layer == 3)
17601778
{
1761-
int main_data_begin = L3_read_side_info(bs_frame, scratch.gr_info, hdr);
1779+
int main_data_begin = L3_read_side_info(bs_frame, p_scratch->gr_info, hdr);
17621780
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
17631781
{
17641782
mp3dec_init(dec);
17651783
return 0;
17661784
}
1767-
success = L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
1785+
success = L3_restore_reservoir(dec, bs_frame, p_scratch, main_data_begin);
17681786
if (success)
17691787
{
17701788
for (igr = 0; igr < (HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm += 576*info->channels)
17711789
{
1772-
memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
1773-
L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
1774-
mp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, pcm, scratch.syn[0]);
1790+
memset(p_scratch->grbuf[0], 0, 576*2*sizeof(float));
1791+
L3_decode(dec, p_scratch, p_scratch->gr_info + igr*info->channels, info->channels);
1792+
mp3d_synth_granule(dec->qmf_state, p_scratch->grbuf[0], 18, info->channels, pcm, p_scratch->syn[0]);
17751793
}
17761794
}
1777-
L3_save_reservoir(dec, &scratch);
1795+
L3_save_reservoir(dec, p_scratch);
17781796
} else
17791797
{
17801798
#ifdef MINIMP3_ONLY_MP3
17811799
return 0;
17821800
#else /* MINIMP3_ONLY_MP3 */
1801+
1802+
#if MINIMP3_STACK_OPT
1803+
L12_scale_info *sci=&(dec->sci);;
1804+
memset(sci,0,sizeof(L12_scale_info));
1805+
#else
17831806
L12_scale_info sci[1];
1807+
#endif
17841808
L12_read_scale_info(hdr, bs_frame, sci);
1785-
1786-
memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
1809+
memset(p_scratch->grbuf[0], 0, 576*2*sizeof(float));
17871810
for (i = 0, igr = 0; igr < 3; igr++)
17881811
{
1789-
if (12 == (i += L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
1812+
if (12 == (i += L12_dequantize_granule(p_scratch->grbuf[0] + i, bs_frame, sci, info->layer | 1)))
17901813
{
17911814
i = 0;
1792-
L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
1793-
mp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, pcm, scratch.syn[0]);
1794-
memset(scratch.grbuf[0], 0, 576*2*sizeof(float));
1815+
L12_apply_scf_384(sci, sci->scf + igr, p_scratch->grbuf[0]);
1816+
mp3d_synth_granule(dec->qmf_state, p_scratch->grbuf[0], 12, info->channels, pcm, p_scratch->syn[0]);
1817+
memset(p_scratch->grbuf[0], 0, 576*2*sizeof(float));
17951818
pcm += 384*info->channels;
17961819
}
17971820
if (bs_frame->pos > bs_frame->limit)

0 commit comments

Comments
 (0)