diff options
Diffstat (limited to 'shared-module')
| -rw-r--r-- | shared-module/audiomp3/MP3Decoder.c (renamed from shared-module/audiomp3/MP3File.c) | 76 | ||||
| -rw-r--r-- | shared-module/audiomp3/MP3Decoder.h (renamed from shared-module/audiomp3/MP3File.h) | 2 |
2 files changed, 54 insertions, 24 deletions
diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3Decoder.c index 0aa4f24a6..30357c616 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -25,18 +25,21 @@ * THE SOFTWARE. */ -#include "shared-bindings/audiomp3/MP3File.h" +#include "shared-bindings/audiomp3/MP3Decoder.h" #include <stdint.h> #include <string.h> +#include <math.h> #include "py/mperrno.h" #include "py/runtime.h" -#include "shared-module/audiomp3/MP3File.h" +#include "shared-module/audiomp3/MP3Decoder.h" #include "supervisor/shared/translate.h" #include "lib/mp3/src/mp3common.h" +#define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) + /** Fill the input buffer if it is less than half full. * * Returns true if the input buffer contains any useful data, @@ -143,7 +146,7 @@ STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameIn do { err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); if (err == ERR_MP3_NONE) { - break; + break; } CONSUME(self, 1); mp3file_find_sync_word(self); @@ -165,7 +168,6 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self, // than the two 4kB output buffers, except that the alignment allows to // never allocate that extra frame buffer. - self->file = file; self->inbuf_length = 2048; self->inbuf_offset = self->inbuf_length; self->inbuf = m_malloc(self->inbuf_length, false); @@ -181,40 +183,56 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self, translate("Couldn't allocate decoder")); } - mp3file_find_sync_word(self); - MP3FrameInfo fi; - if(!mp3file_get_next_frame_info(self, &fi)) { - mp_raise_msg(&mp_type_RuntimeError, - translate("Failed to parse MP3 file")); - } - - self->sample_rate = fi.samprate; - self->channel_count = fi.nChans; - self->frame_buffer_size = fi.outputSamps*sizeof(int16_t); - if ((intptr_t)buffer & 1) { buffer += 1; buffer_size -= 1; } - if (buffer_size >= 2 * self->frame_buffer_size) { - self->len = buffer_size / 2 / self->frame_buffer_size * self->frame_buffer_size; + if (buffer_size >= 2 * MAX_BUFFER_LEN) { self->buffers[0] = (int16_t*)(void*)buffer; - self->buffers[1] = (int16_t*)(void*)buffer + self->len; + self->buffers[1] = (int16_t*)(void*)(buffer + MAX_BUFFER_LEN); } else { - self->len = 2 * self->frame_buffer_size; - self->buffers[0] = m_malloc(self->len, false); + self->buffers[0] = m_malloc(MAX_BUFFER_LEN, false); if (self->buffers[0] == NULL) { common_hal_audiomp3_mp3file_deinit(self); mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer")); } - self->buffers[1] = m_malloc(self->len, false); + self->buffers[1] = m_malloc(MAX_BUFFER_LEN, false); if (self->buffers[1] == NULL) { common_hal_audiomp3_mp3file_deinit(self); mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer")); } } + + common_hal_audiomp3_mp3file_set_file(self, file); +} + +void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t* self, pyb_file_obj_t* file) { + self->file = file; + f_lseek(&self->file->fp, 0); + self->inbuf_offset = self->inbuf_length; + self->eof = 0; + self->other_channel = -1; + mp3file_update_inbuf(self); + mp3file_find_sync_word(self); + // It **SHOULD** not be necessary to do this; the buffer should be filled + // with fresh content before it is returned by get_buffer(). The fact that + // this is necessary to avoid a glitch at the start of playback of a second + // track using the same decoder object means there's still a bug in + // get_buffer() that I didn't understand. + memset(self->buffers[0], 0, MAX_BUFFER_LEN); + memset(self->buffers[1], 0, MAX_BUFFER_LEN); + MP3FrameInfo fi; + if(!mp3file_get_next_frame_info(self, &fi)) { + mp_raise_msg(&mp_type_RuntimeError, + translate("Failed to parse MP3 file")); + } + + self->sample_rate = fi.samprate; + self->channel_count = fi.nChans; + self->frame_buffer_size = fi.outputSamps*sizeof(int16_t); + self->len = 2 * self->frame_buffer_size; } void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t* self) { @@ -280,7 +298,6 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* channel = 0; } - *bufptr = (uint8_t*)(self->buffers[self->buffer_index] + channel); *buffer_length = self->frame_buffer_size; if (channel == self->other_channel) { @@ -289,11 +306,12 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* return GET_BUFFER_MORE_DATA; } - self->other_channel = 1-channel; - self->other_buffer_index = self->buffer_index; self->buffer_index = !self->buffer_index; + self->other_channel = 1-channel; + self->other_buffer_index = self->buffer_index; int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + *bufptr = (uint8_t*)buffer; mp3file_skip_id3v2(self); if (!mp3file_find_sync_word(self)) { @@ -322,3 +340,13 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si *spacing = 1; } } + +float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self) { + float sumsq = 0.f; + // Assumes no DC component to the audio. Is that a safe assumption? + int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + for(size_t i=0; i<self->frame_buffer_size / sizeof(int16_t); i++) { + sumsq += (float)buffer[i] * buffer[i]; + } + return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t)); +} diff --git a/shared-module/audiomp3/MP3File.h b/shared-module/audiomp3/MP3Decoder.h index 9d99e8d1f..9ee1d0949 100644 --- a/shared-module/audiomp3/MP3File.h +++ b/shared-module/audiomp3/MP3Decoder.h @@ -67,4 +67,6 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si bool* single_buffer, bool* samples_signed, uint32_t* max_buffer_length, uint8_t* spacing); +float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t* self); + #endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MP3FILE_H |
