Skip to content

Commit 1aa17b3

Browse files
authored
Merge pull request #9284 from jepler/mp3-stream
MP3: Stream them
2 parents 76cc0a1 + 6c9eaf1 commit 1aa17b3

File tree

8 files changed

+342
-145
lines changed

8 files changed

+342
-145
lines changed

ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ QSPI_FLASH_FILESYSTEM = 1
1212
EXTERNAL_FLASH_DEVICES = GD25Q16C
1313
LONGINT_IMPL = MPZ
1414

15+
CIRCUITPY_AUDIOMP3 = 0
16+
CIRCUITPY_JPEGIO = 0
1517
CIRCUITPY_PS2IO = 1
1618
CIRCUITPY_SYNTHIO = 0
17-
CIRCUITPY_JPEGIO = 0

ports/atmel-samd/boards/monster_m4sk/mpconfigboard.mk

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,13 @@ CHIP_FAMILY = samd51
1010
QSPI_FLASH_FILESYSTEM = 1
1111
EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ"
1212
LONGINT_IMPL = MPZ
13-
CIRCUITPY_SYNTHIO = 0
13+
14+
CIRCUITPY_EPAPERDISPLAY = 0
15+
CIRCUITPY_FLOPPYIO = 0
16+
CIRCUITPY_I2CDISPLAYBUS = 0
17+
CIRCUITPY_KEYPAD = 0
18+
CIRCUITPY_KEYPAD = 0
19+
CIRCUITPY_PARALLELDISPLAYBUS = 0
20+
CIRCUITPY_RGBMATRIX = 0
21+
CIRCUITPY_SHARPDISPLAY = 0
22+
CIRCUITPY_SYNTHIO = 1

ports/unix/variants/coverage/mpconfigvariant.mk

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ SRC_BITMAP := \
3434
shared-bindings/audiomixer/__init__.c \
3535
shared-bindings/audiomixer/Mixer.c \
3636
shared-bindings/audiomixer/MixerVoice.c \
37+
shared-bindings/audiomp3/__init__.c \
38+
shared-bindings/audiomp3/MP3Decoder.c \
3739
shared-bindings/bitmapfilter/__init__.c \
3840
shared-bindings/bitmaptools/__init__.c \
3941
shared-bindings/codeop/__init__.c \
@@ -62,6 +64,7 @@ SRC_BITMAP := \
6264
shared-module/audiocore/RawSample.c \
6365
shared-module/audiocore/WaveFile.c \
6466
shared-module/audiomixer/__init__.c \
67+
shared-module/audiomp3/MP3Decoder.c \
6568
shared-module/audiomixer/Mixer.c \
6669
shared-module/audiomixer/MixerVoice.c \
6770
shared-module/bitmapfilter/__init__.c \
@@ -88,10 +91,32 @@ SRC_BITMAP := \
8891

8992
SRC_C += $(SRC_BITMAP)
9093

94+
SRC_C += $(addprefix lib/mp3/src/, \
95+
bitstream.c \
96+
buffers.c \
97+
dct32.c \
98+
dequant.c \
99+
dqchan.c \
100+
huffman.c \
101+
hufftabs.c \
102+
imdct.c \
103+
mp3dec.c \
104+
mp3tabs.c \
105+
polyphase.c \
106+
scalfact.c \
107+
stproc.c \
108+
subband.c \
109+
trigtabs.c \
110+
)
111+
112+
$(BUILD)/lib/mp3/src/buffers.o: CFLAGS += -include "shared-module/audiomp3/__init__.h" -D'MPDEC_ALLOCATOR(x)=malloc(x)' -D'MPDEC_FREE(x)=free(x)' -fwrapv
113+
91114
CFLAGS += \
92115
-DCIRCUITPY_AESIO=1 \
93116
-DCIRCUITPY_AUDIOCORE=1 \
94117
-DCIRCUITPY_AUDIOMIXER=1 \
118+
-DCIRCUITPY_AUDIOMP3=1 \
119+
-DCIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR=0 \
95120
-DCIRCUITPY_AUDIOCORE_DEBUG=1 \
96121
-DCIRCUITPY_BITMAPTOOLS=1 \
97122
-DCIRCUITPY_CODEOP=1 \

shared-bindings/audiomp3/MP3Decoder.c

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "shared/runtime/context_manager_helpers.h"
1111
#include "py/objproperty.h"
1212
#include "py/runtime.h"
13+
#include "py/stream.h"
1314
#include "shared-bindings/audiomp3/MP3Decoder.h"
1415
#include "shared-bindings/util.h"
1516

@@ -27,13 +28,13 @@
2728
//| """Load a .mp3 file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
2829
//|
2930
//| :param Union[str, typing.BinaryIO] file: The name of a mp3 file (preferred) or an already opened mp3 file
30-
//| :param ~circuitpython_typing.WriteableBuffer buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two buffers are allocated internally. The specific buffer size required depends on the mp3 file.
31+
//| :param ~circuitpython_typing.WriteableBuffer buffer: Optional pre-allocated buffer, that will be split and used for buffering the data. The buffer is split into two parts for decoded data and the remainder is used for pre-decoded data. When playing from a socket, a larger buffer can help reduce playback glitches at the expense of increased memory usage.
3132
//|
3233
//| Playback of mp3 audio is CPU intensive, and the
3334
//| exact limit depends on many factors such as the particular
34-
//| microcontroller, SD card or flash performance, and other
35-
//| code in use such as displayio. If playback is garbled,
36-
//| skips, or plays as static, first try using a "simpler" mp3:
35+
//| microcontroller, SD card or flash performance, network performance, and
36+
//| other code in use such as displayio. If playback is garbled, skips, or plays as
37+
//| static, first try using a "simpler" mp3:
3738
//|
3839
//| * Use constant bit rate (CBR) not VBR or ABR (variable or average bit rate) when encoding your mp3 file
3940
//| * Use a lower sample rate (e.g., 11.025kHz instead of 48kHz)
@@ -63,21 +64,31 @@
6364
//| while a.playing:
6465
//| pass
6566
//| print("stopped")
67+
//|
68+
//| It is possible to seek within a file before playing it::
69+
//|
70+
//| with open("/test.mp3", "rb") as stream:
71+
//| stream.seek(128000 * 30 // 8) # Seek about 30s into a 128kbit/s stream
72+
//| decoder.file = stream
73+
//|
74+
//| If the stream is played with ``loop = True``, the loop will start at the beginning.
6675
//| """
6776
//| ...
6877

6978
static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
7079
mp_arg_check_num(n_args, n_kw, 1, 2, false);
71-
mp_obj_t arg = args[0];
80+
mp_obj_t stream = args[0];
7281

73-
if (mp_obj_is_str(arg)) {
74-
arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb));
82+
if (mp_obj_is_str(stream)) {
83+
stream = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), stream, MP_ROM_QSTR(MP_QSTR_rb));
7584
}
7685

7786
audiomp3_mp3file_obj_t *self = m_new_obj_with_finaliser(audiomp3_mp3file_obj_t);
7887
self->base.type = &audiomp3_mp3file_type;
7988

80-
if (!mp_obj_is_type(arg, &mp_type_fileio)) {
89+
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream, MP_STREAM_OP_READ);
90+
91+
if (stream_p->is_text) {
8192
mp_raise_TypeError(MP_ERROR_TEXT("file must be a file opened in byte mode"));
8293
}
8394
uint8_t *buffer = NULL;
@@ -88,8 +99,7 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar
8899
buffer = bufinfo.buf;
89100
buffer_size = bufinfo.len;
90101
}
91-
common_hal_audiomp3_mp3file_construct(self, MP_OBJ_TO_PTR(arg),
92-
buffer, buffer_size);
102+
common_hal_audiomp3_mp3file_construct(self, stream, buffer, buffer_size);
93103

94104
return MP_OBJ_FROM_PTR(self);
95105
}
@@ -131,17 +141,19 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomp3_mp3file___exit___obj, 4, 4,
131141
static mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) {
132142
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
133143
check_for_deinit(self);
134-
return self->file;
144+
return self->stream;
135145
}
136146
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_file_obj, audiomp3_mp3file_obj_get_file);
137147

138-
static mp_obj_t audiomp3_mp3file_obj_set_file(mp_obj_t self_in, mp_obj_t file) {
148+
static mp_obj_t audiomp3_mp3file_obj_set_file(mp_obj_t self_in, mp_obj_t stream) {
139149
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
140150
check_for_deinit(self);
141-
if (!mp_obj_is_type(file, &mp_type_fileio)) {
151+
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream, MP_STREAM_OP_READ);
152+
153+
if (stream_p->is_text) {
142154
mp_raise_TypeError(MP_ERROR_TEXT("file must be a file opened in byte mode"));
143155
}
144-
common_hal_audiomp3_mp3file_set_file(self, file);
156+
common_hal_audiomp3_mp3file_set_file(self, stream);
145157
return mp_const_none;
146158
}
147159
MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_file_obj, audiomp3_mp3file_obj_set_file);

shared-bindings/audiomp3/MP3Decoder.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
extern const mp_obj_type_t audiomp3_mp3file_type;
1616

1717
void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self,
18-
pyb_file_obj_t *file, uint8_t *buffer, size_t buffer_size);
18+
mp_obj_t stream, uint8_t *buffer, size_t buffer_size);
1919

20-
void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, pyb_file_obj_t *file);
20+
void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t stream);
2121
void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self);
2222
bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self);
2323
uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self);

0 commit comments

Comments
 (0)