Skip to content

Commit 8384e46

Browse files
authored
Merge pull request #2384 from jepler/mp3-fixes
MP3: skip id3v2 tags, make "bartlebeats" tracks playable
2 parents 6c3d555 + 91a1706 commit 8384e46

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

shared-module/audiocore/__init__.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
5252

5353
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) {
5454
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
55-
proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj));
55+
proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, audio_channel);
5656
}
5757

5858
audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,

shared-module/audiocore/__init__.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ typedef enum {
4242
typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t);
4343
typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t);
4444
typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t);
45-
typedef void (*audiosample_reset_buffer_fun)(mp_obj_t);
45+
typedef void (*audiosample_reset_buffer_fun)(mp_obj_t,
46+
bool single_channel, uint8_t audio_channel);
4647
typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t,
4748
bool single_channel, uint8_t channel, uint8_t** buffer,
4849
uint32_t* buffer_length);

shared-module/audiomp3/MP3File.c

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,39 @@ STATIC bool mp3file_update_inbuf(audiomp3_mp3file_obj_t* self) {
8888
#define BYTES_LEFT(self) (self->inbuf_length - self->inbuf_offset)
8989
#define CONSUME(self, n) (self->inbuf_offset += n)
9090

91+
// http://id3.org/d3v2.3.0
92+
// http://id3.org/id3v2.3.0
93+
STATIC void mp3file_skip_id3v2(audiomp3_mp3file_obj_t* self) {
94+
mp3file_update_inbuf(self);
95+
if (BYTES_LEFT(self) < 10) {
96+
return;
97+
}
98+
uint8_t *data = READ_PTR(self);
99+
if (!(
100+
data[0] == 'I' &&
101+
data[1] == 'D' &&
102+
data[2] == '3' &&
103+
data[3] != 0xff &&
104+
data[4] != 0xff &&
105+
(data[5] & 0x1f) == 0 &&
106+
(data[6] & 0x80) == 0 &&
107+
(data[7] & 0x80) == 0 &&
108+
(data[8] & 0x80) == 0 &&
109+
(data[9] & 0x80) == 0)) {
110+
return;
111+
}
112+
uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]);
113+
size += 10; // size excludes the "header" (but not the "extended header")
114+
// First, deduct from size whatever is left in buffer
115+
uint32_t to_consume = MIN(size, BYTES_LEFT(self));
116+
CONSUME(self, to_consume);
117+
size -= to_consume;
118+
119+
// Next, seek in the file after the header
120+
f_lseek(&self->file->fp, f_tell(&self->file->fp) + size);
121+
return;
122+
}
123+
91124
/* If a sync word can be found, advance to it and return true. Otherwise,
92125
* return false.
93126
*/
@@ -106,7 +139,15 @@ STATIC bool mp3file_find_sync_word(audiomp3_mp3file_obj_t* self) {
106139
}
107140

108141
STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameInfo* fi) {
109-
int err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self));
142+
int err;
143+
do {
144+
err = MP3GetNextFrameInfo(self->decoder, fi, READ_PTR(self));
145+
if (err == ERR_MP3_NONE) {
146+
break;
147+
}
148+
CONSUME(self, 1);
149+
mp3file_find_sync_word(self);
150+
} while (!self->eof);
110151
return err == ERR_MP3_NONE;
111152
}
112153

@@ -223,6 +264,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
223264
self->eof = 0;
224265
self->other_channel = -1;
225266
mp3file_update_inbuf(self);
267+
mp3file_skip_id3v2(self);
226268
mp3file_find_sync_word(self);
227269
}
228270

@@ -253,6 +295,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
253295
self->buffer_index = !self->buffer_index;
254296
int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index];
255297

298+
mp3file_skip_id3v2(self);
256299
if (!mp3file_find_sync_word(self)) {
257300
return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
258301
}

0 commit comments

Comments
 (0)