MP3File: Fix stereo playback on samd AudioOut
There were several problems with the way this worked -- the read_count approach was too complicated and I made a mistake "simplifying" it from WaveFile. And when the right channel was returned, it was off by 1 byte, making it into static. Instead, directly track which is the "other" channel that has data available, and by using the right data type make the "+ channel" arithmetic give the right result. This requires a double cast (int16_t*)(void*) due to an alignment warning; the alignment is now ensured manually, but the compiler doesn't make the necessary inference that the low address bit must be clear.
This commit is contained in:
parent
8c841af946
commit
1cdac3f16a
@ -151,10 +151,13 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
|
||||
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;
|
||||
self->buffers[0] = buffer;
|
||||
self->buffers[1] = buffer + self->len;
|
||||
self->buffers[0] = (int16_t*)(void*)buffer;
|
||||
self->buffers[1] = (int16_t*)(void*)buffer + self->len;
|
||||
} else {
|
||||
self->len = 2 * self->frame_buffer_size;
|
||||
self->buffers[0] = m_malloc(self->len, false);
|
||||
@ -218,6 +221,7 @@ void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t* self,
|
||||
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);
|
||||
}
|
||||
@ -234,26 +238,30 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
uint16_t channel_read_count = self->channel_read_count[channel]++;
|
||||
bool need_more_data = self->read_count++ == channel_read_count;
|
||||
|
||||
*bufptr = self->buffers[self->buffer_index] + channel;
|
||||
*bufptr = (uint8_t*)(self->buffers[self->buffer_index] + channel);
|
||||
*buffer_length = self->frame_buffer_size;
|
||||
|
||||
if (need_more_data) {
|
||||
self->buffer_index = !self->buffer_index;
|
||||
int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index];
|
||||
if (channel == self->other_channel) {
|
||||
*bufptr = (uint8_t*)(self->buffers[self->other_buffer_index] + channel);
|
||||
self->other_channel = -1;
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
if (!mp3file_find_sync_word(self)) {
|
||||
return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
|
||||
}
|
||||
int bytes_left = BYTES_LEFT(self);
|
||||
uint8_t *inbuf = READ_PTR(self);
|
||||
int err = MP3Decode(self->decoder, &inbuf, &bytes_left, buffer, 0);
|
||||
CONSUME(self, BYTES_LEFT(self) - bytes_left);
|
||||
if (err) {
|
||||
return GET_BUFFER_DONE;
|
||||
}
|
||||
self->other_channel = 1-channel;
|
||||
self->other_buffer_index = self->buffer_index;
|
||||
|
||||
self->buffer_index = !self->buffer_index;
|
||||
int16_t *buffer = (int16_t *)(void *)self->buffers[self->buffer_index];
|
||||
|
||||
if (!mp3file_find_sync_word(self)) {
|
||||
return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
|
||||
}
|
||||
int bytes_left = BYTES_LEFT(self);
|
||||
uint8_t *inbuf = READ_PTR(self);
|
||||
int err = MP3Decode(self->decoder, &inbuf, &bytes_left, buffer, 0);
|
||||
CONSUME(self, BYTES_LEFT(self) - bytes_left);
|
||||
if (err) {
|
||||
return GET_BUFFER_DONE;
|
||||
}
|
||||
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
|
@ -39,7 +39,7 @@ typedef struct {
|
||||
uint8_t* inbuf;
|
||||
uint32_t inbuf_length;
|
||||
uint32_t inbuf_offset;
|
||||
uint8_t* buffers[2];
|
||||
int16_t* buffers[2];
|
||||
uint32_t len;
|
||||
uint32_t frame_buffer_size;
|
||||
|
||||
@ -50,8 +50,8 @@ typedef struct {
|
||||
uint8_t channel_count;
|
||||
bool eof;
|
||||
|
||||
uint16_t read_count;
|
||||
uint16_t channel_read_count[2];
|
||||
int8_t other_channel;
|
||||
int8_t other_buffer_index;
|
||||
} audiomp3_mp3file_obj_t;
|
||||
|
||||
// These are not available from Python because it may be called in an interrupt.
|
||||
|
Loading…
Reference in New Issue
Block a user