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.
This commit is contained in:
parent
6f8c9deda8
commit
98b0029a29
|
@ -232,6 +232,22 @@ const mp_obj_property_t audiomp3_mp3file_rms_level_obj = {
|
|||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
//| samples_decoded: int
|
||||
//| """The number of audio samples decoded from the current file. (read only)"""
|
||||
//|
|
||||
STATIC mp_obj_t audiomp3_mp3file_obj_get_samples_decoded(mp_obj_t self_in) {
|
||||
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_samples_decoded(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_samples_decoded_obj, audiomp3_mp3file_obj_get_samples_decoded);
|
||||
|
||||
const mp_obj_property_t audiomp3_mp3file_samples_decoded_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&audiomp3_mp3file_get_samples_decoded_obj,
|
||||
MP_ROM_NONE,
|
||||
MP_ROM_NONE},
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
|
||||
// Methods
|
||||
|
@ -245,6 +261,7 @@ STATIC const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiomp3_mp3file_bits_per_sample_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiomp3_mp3file_channel_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_samples_decoded), MP_ROM_PTR(&audiomp3_mp3file_samples_decoded_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table);
|
||||
|
||||
|
|
|
@ -46,5 +46,6 @@ void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, u
|
|||
uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self);
|
||||
uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self);
|
||||
float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);
|
||||
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MP3FILE_H
|
||||
|
|
|
@ -258,6 +258,7 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, pyb_file
|
|||
self->channel_count = fi.nChans;
|
||||
self->frame_buffer_size = fi.outputSamps * sizeof(int16_t);
|
||||
self->len = 2 * self->frame_buffer_size;
|
||||
self->samples_decoded = 0;
|
||||
}
|
||||
|
||||
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) {
|
|||
self->buffers[0] = NULL;
|
||||
self->buffers[1] = NULL;
|
||||
self->file = NULL;
|
||||
self->samples_decoded = 0;
|
||||
}
|
||||
|
||||
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 *
|
|||
if (channel == self->other_channel) {
|
||||
*bufptr = (uint8_t *)(self->buffers[self->other_buffer_index] + channel);
|
||||
self->other_channel = -1;
|
||||
self->samples_decoded += *buffer_length / sizeof(int16_t);
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
|
@ -359,6 +362,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
self);
|
||||
}
|
||||
|
||||
self->samples_decoded += *buffer_length / sizeof(int16_t);
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
|
@ -384,3 +388,7 @@ float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self) {
|
|||
}
|
||||
return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t));
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self) {
|
||||
return self->samples_decoded;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ typedef struct {
|
|||
|
||||
int8_t other_channel;
|
||||
int8_t other_buffer_index;
|
||||
|
||||
uint32_t samples_decoded;
|
||||
} audiomp3_mp3file_obj_t;
|
||||
|
||||
// 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
|
|||
|
||||
float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);
|
||||
|
||||
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H
|
||||
|
|
Loading…
Reference in New Issue