|
36 | 36 |
|
37 | 37 | #include "shared-module/audiomp3/MP3Decoder.h"
|
38 | 38 | #include "supervisor/shared/translate.h"
|
| 39 | +#include "supervisor/background_callback.h" |
39 | 40 | #include "lib/mp3/src/mp3common.h"
|
40 | 41 |
|
41 | 42 | #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t))
|
42 | 43 |
|
43 |
| -/** Fill the input buffer if it is less than half full. |
| 44 | +/** Fill the input buffer unconditionally. |
44 | 45 | *
|
45 | 46 | * Returns true if the input buffer contains any useful data,
|
46 | 47 | * false otherwise. (The input buffer will be padded to the end with
|
|
50 | 51 | *
|
51 | 52 | * Sets self->eof if any read of the file returns 0 bytes
|
52 | 53 | */
|
53 |
| -STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) { |
54 |
| - // If buffer is over half full, do nothing |
55 |
| - if (self->inbuf_offset < self->inbuf_length/2) return true; |
56 |
| - |
| 54 | +STATIC bool mp3file_update_inbuf_unconditional(audiomp3_mp3file_obj_t* self) { |
57 | 55 | // If we didn't previously reach the end of file, we can try reading now
|
58 | 56 | if (!self->eof) {
|
59 | 57 |
|
@@ -87,14 +85,37 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
|
87 | 85 | return self->inbuf_offset < self->inbuf_length;
|
88 | 86 | }
|
89 | 87 |
|
| 88 | +STATIC int bg_updates; |
| 89 | + |
| 90 | +/** Update the inbuf from a background callback. |
| 91 | + * |
| 92 | + * This variant is introduced so that at the site of the |
| 93 | + * add_background_callback_core call, the prototype matches. |
| 94 | + */ |
| 95 | +STATIC void mp3file_update_inbuf_cb(void* self) { |
| 96 | + bg_updates ++; |
| 97 | + mp3file_update_inbuf_unconditional(self); |
| 98 | +} |
| 99 | + |
| 100 | +/** Fill the input buffer if it is less than half full. |
| 101 | + * |
| 102 | + * Returns the same as mp3file_update_inbuf_unconditional. |
| 103 | + */ |
| 104 | +STATIC bool mp3file_update_inbuf_half(audiomp3_mp3file_obj_t* self) { |
| 105 | + // If buffer is over half full, do nothing |
| 106 | + if (self->inbuf_offset < self->inbuf_length/2) return true; |
| 107 | + |
| 108 | + return mp3file_update_inbuf_unconditional(self); |
| 109 | +} |
| 110 | + |
90 | 111 | #define READ_PTR(self) (self->inbuf + self->inbuf_offset)
|
91 | 112 | #define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset)
|
92 | 113 | #define CONSUME(self, n) (self->inbuf_offset += n)
|
93 | 114 |
|
94 | 115 | // http://id3.org/d3v2.3.0
|
95 | 116 | // http://id3.org/id3v2.3.0
|
96 | 117 | STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) {
|
97 |
| - mp3file_update_inbuf(self); |
| 118 | + mp3file_update_inbuf_half(self); |
98 | 119 | if (BYTES_LEFT(self) < 10) {
|
99 | 120 | return;
|
100 | 121 | }
|
@@ -129,11 +150,11 @@ STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) {
|
129 | 150 | */
|
130 | 151 | STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) {
|
131 | 152 | do {
|
132 |
| - mp3file_update_inbuf(self); |
| 153 | + mp3file_update_inbuf_half(self); |
133 | 154 | int offset = MP3FindSyncWord(READ_PTR(self), BYTES_LEFT(self));
|
134 | 155 | if (offset >= 0) {
|
135 | 156 | CONSUME(self, offset);
|
136 |
| - mp3file_update_inbuf(self); |
| 157 | + mp3file_update_inbuf_half(self); |
137 | 158 | return true;
|
138 | 159 | }
|
139 | 160 | CONSUME(self, MAX(0, BYTES_LEFT(self) - 16));
|
@@ -214,7 +235,7 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file
|
214 | 235 | self->inbuf_offset = self->inbuf_length;
|
215 | 236 | self->eof = 0;
|
216 | 237 | self->other_channel = -1;
|
217 |
| - mp3file_update_inbuf(self); |
| 238 | + mp3file_update_inbuf_half(self); |
218 | 239 | mp3file_find_sync_word(self);
|
219 | 240 | // It **SHOULD** not be necessary to do this; the buffer should be filled
|
220 | 241 | // with fresh content before it is returned by get_buffer(). The fact that
|
@@ -281,7 +302,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
|
281 | 302 | self->inbuf_offset = self->inbuf_length;
|
282 | 303 | self->eof = 0;
|
283 | 304 | self->other_channel = -1;
|
284 |
| - mp3file_update_inbuf(self); |
| 305 | + mp3file_update_inbuf_half(self); |
285 | 306 | mp3file_skip_id3v2(self);
|
286 | 307 | mp3file_find_sync_word(self);
|
287 | 308 | }
|
@@ -321,6 +342,14 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
|
321 | 342 | uint8_t *inbuf = READ_PTR(self);
|
322 | 343 | int err = MP3Decode(self->decoder, &inbuf, &bytes_left, buffer, 0);
|
323 | 344 | CONSUME(self, BYTES_LEFT(self) - bytes_left);
|
| 345 | + |
| 346 | + if (self->inbuf_offset >= 512) { |
| 347 | + background_callback_add( |
| 348 | + &self->inbuf_fill_cb, |
| 349 | + mp3file_update_inbuf_cb, |
| 350 | + self); |
| 351 | + } |
| 352 | + |
324 | 353 | if (err) {
|
325 | 354 | return GET_BUFFER_DONE;
|
326 | 355 | }
|
|
0 commit comments