diff options
| author | Scott Shawcroft <scott@adafruit.com> | 2019-12-15 21:59:39 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-12-15 21:59:39 -0800 |
| commit | 8384e4676b5f7e4c06fd8f1db53382b6f3e6d175 (patch) | |
| tree | 4dc7ab2940122be7063714eece25564e22a4cf3b | |
| parent | 6c3d555b873fb7dddfa09ff24c6630c1aae47d3d (diff) | |
| parent | 91a1706160aa653cb00c7910b0930df679bcdd21 (diff) | |
Merge pull request #2384 from jepler/mp3-fixes
MP3: skip id3v2 tags, make "bartlebeats" tracks playable
| -rw-r--r-- | shared-module/audiocore/__init__.c | 2 | ||||
| -rw-r--r-- | shared-module/audiocore/__init__.h | 3 | ||||
| -rw-r--r-- | shared-module/audiomp3/MP3File.c | 45 |
3 files changed, 47 insertions, 3 deletions
diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index 1553dbe96..ac9d41b60 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -52,7 +52,7 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) { void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj)); + proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, audio_channel); } audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 38c1f5aeb..7a56454b8 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -42,7 +42,8 @@ typedef enum { typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t); typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t); typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t); -typedef void (*audiosample_reset_buffer_fun)(mp_obj_t); +typedef void (*audiosample_reset_buffer_fun)(mp_obj_t, + bool single_channel, uint8_t audio_channel); typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t, bool single_channel, uint8_t channel, uint8_t** buffer, uint32_t* buffer_length); diff --git a/shared-module/audiomp3/MP3File.c b/shared-module/audiomp3/MP3File.c index f4861da36..0aa4f24a6 100644 --- a/shared-module/audiomp3/MP3File.c +++ b/shared-module/audiomp3/MP3File.c @@ -88,6 +88,39 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) { #define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset) #define CONSUME(self, n) (self->inbuf_offset += n) +// http://id3.org/d3v2.3.0 +// http://id3.org/id3v2.3.0 +STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) { + mp3file_update_inbuf(self); + if (BYTES_LEFT(self) < 10) { + return; + } + uint8_t *data = READ_PTR(self); + if (!( + data[0] == 'I' && + data[1] == 'D' && + data[2] == '3' && + data[3] != 0xff && + data[4] != 0xff && + (data[5] & 0x1f) == 0 && + (data[6] & 0x80) == 0 && + (data[7] & 0x80) == 0 && + (data[8] & 0x80) == 0 && + (data[9] & 0x80) == 0)) { + return; + } + uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); + size += 10; // size excludes the "header" (but not the "extended header") + // First, deduct from size whatever is left in buffer + uint32_t to_consume = MIN(size, BYTES_LEFT(self)); + CONSUME(self, to_consume); + size -= to_consume; + + // Next, seek in the file after the header + f_lseek(&self->file->fp, f_tell(&self->file->fp) + size); + return; +} + /* If a sync word can be found, advance to it and return true. Otherwise, * return false. */ @@ -106,7 +139,15 @@ STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) { } STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameInfo* fi) { - int err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); + int err; + do { + err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self)); + if (err == ERR_MP3_NONE) { + break; + } + CONSUME(self, 1); + mp3file_find_sync_word(self); + } while (!self->eof); return err == ERR_MP3_NONE; } @@ -223,6 +264,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self, self->eof = 0; self->other_channel = -1; mp3file_update_inbuf(self); + mp3file_skip_id3v2(self); mp3file_find_sync_word(self); } @@ -253,6 +295,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t* self->buffer_index = !self->buffer_index; int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index]; + mp3file_skip_id3v2(self); if (!mp3file_find_sync_word(self)) { return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR; } |
