Skip to content

Commit 98b0029

Browse files
committed
audiomp3: add decoded_samples property
In my testing, there is no way to accurately know how far into a MP3 file you're currently playing. You can use monotonic time, but that can have drift versus the audio playback system, which may not be running at exactly the expected sample rate. To allow syncing animation with timestamps in a MP3 file, this presents a new property, decoded_samples, that records the number of audio samples sent out of the decoder. While this may not be a completely accurate time, due to mixer delays, it's much better position that the monotonic clock difference. Implementation is keeping track of this value in the mp3file structure and adding to it whenever data is sent out of the decoder. The property implementation was a copy/paste from current properties in the audiomp3 files.
1 parent 6f8c9de commit 98b0029

File tree

4 files changed

+30
-0
lines changed

4 files changed

+30
-0
lines changed

shared-bindings/audiomp3/MP3Decoder.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,22 @@ const mp_obj_property_t audiomp3_mp3file_rms_level_obj = {
232232
MP_ROM_NONE},
233233
};
234234

235+
//| samples_decoded: int
236+
//| """The number of audio samples decoded from the current file. (read only)"""
237+
//|
238+
STATIC mp_obj_t audiomp3_mp3file_obj_get_samples_decoded(mp_obj_t self_in) {
239+
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
240+
check_for_deinit(self);
241+
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_samples_decoded(self));
242+
}
243+
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_samples_decoded_obj, audiomp3_mp3file_obj_get_samples_decoded);
244+
245+
const mp_obj_property_t audiomp3_mp3file_samples_decoded_obj = {
246+
.base.type = &mp_type_property,
247+
.proxy = {(mp_obj_t)&audiomp3_mp3file_get_samples_decoded_obj,
248+
MP_ROM_NONE,
249+
MP_ROM_NONE},
250+
};
235251

236252
STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
237253
// Methods
@@ -245,6 +261,7 @@ STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
245261
{ MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiomp3_mp3file_bits_per_sample_obj) },
246262
{ MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiomp3_mp3file_channel_count_obj) },
247263
{ MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_obj) },
264+
{ MP_ROM_QSTR(MP_QSTR_samples_decoded), MP_ROM_PTR(&audiomp3_mp3file_samples_decoded_obj) },
248265
};
249266
STATIC MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table);
250267

shared-bindings/audiomp3/MP3Decoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, u
4646
uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self);
4747
uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self);
4848
float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);
49+
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self);
4950

5051
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H

shared-module/audiomp3/MP3Decoder.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, pyb_file
258258
self->channel_count = fi.nChans;
259259
self->frame_buffer_size = fi.outputSamps * sizeof(int16_t);
260260
self->len = 2 * self->frame_buffer_size;
261+
self->samples_decoded = 0;
261262
}
262263

263264
void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) {
@@ -267,6 +268,7 @@ void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) {
267268
self->buffers[0] = NULL;
268269
self->buffers[1] = NULL;
269270
self->file = NULL;
271+
self->samples_decoded = 0;
270272
}
271273

272274
bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self) {
@@ -327,6 +329,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
327329
if (channel == self->other_channel) {
328330
*bufptr = (uint8_t *)(self->buffers[self->other_buffer_index] + channel);
329331
self->other_channel = -1;
332+
self->samples_decoded += *buffer_length / sizeof(int16_t);
330333
return GET_BUFFER_MORE_DATA;
331334
}
332335

@@ -359,6 +362,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
359362
self);
360363
}
361364

365+
self->samples_decoded += *buffer_length / sizeof(int16_t);
362366
return GET_BUFFER_MORE_DATA;
363367
}
364368

@@ -384,3 +388,7 @@ float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self) {
384388
}
385389
return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t));
386390
}
391+
392+
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self) {
393+
return self->samples_decoded;
394+
}

shared-module/audiomp3/MP3Decoder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ typedef struct {
5454

5555
int8_t other_channel;
5656
int8_t other_buffer_index;
57+
58+
uint32_t samples_decoded;
5759
} audiomp3_mp3file_obj_t;
5860

5961
// These are not available from Python because it may be called in an interrupt.
@@ -71,4 +73,6 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool si
7173

7274
float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);
7375

76+
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self);
77+
7478
#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H

0 commit comments

Comments
 (0)