summaryrefslogtreecommitdiff
path: root/shared-module/audiomp3
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module/audiomp3')
-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