summaryrefslogtreecommitdiff
path: root/shared-module
diff options
context:
space:
mode:
Diffstat (limited to 'shared-module')
-rw-r--r--shared-module/_pixelbuf/PixelBuf.c14
-rw-r--r--shared-module/_pixelbuf/PixelBuf.h8
-rw-r--r--shared-module/audiocore/__init__.c2
-rw-r--r--shared-module/audiocore/__init__.h3
-rw-r--r--shared-module/audiomp3/MP3Decoder.c (renamed from shared-module/audiomp3/MP3File.c)119
-rw-r--r--shared-module/audiomp3/MP3Decoder.h (renamed from shared-module/audiomp3/MP3File.h)2
-rw-r--r--shared-module/displayio/Display.c17
-rw-r--r--shared-module/displayio/display_core.c9
-rw-r--r--shared-module/displayio/display_core.h2
9 files changed, 139 insertions, 37 deletions
diff --git a/shared-module/_pixelbuf/PixelBuf.c b/shared-module/_pixelbuf/PixelBuf.c
index d32697239..020151bc3 100644
--- a/shared-module/_pixelbuf/PixelBuf.c
+++ b/shared-module/_pixelbuf/PixelBuf.c
@@ -31,7 +31,7 @@
#include "PixelBuf.h"
#include <string.h>
-void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder) {
+void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder) {
buf[byteorder->byteorder.r] = value >> 16 & 0xff;
buf[byteorder->byteorder.g] = (value >> 8) & 0xff;
buf[byteorder->byteorder.b] = value & 0xff;
@@ -43,15 +43,15 @@ void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj
}
}
-void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
+void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar) {
if (MP_OBJ_IS_INT(item)) {
uint8_t *target = rawbuf ? rawbuf : buf;
pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder);
- if (dotstar) {
+ if (dotstar) {
buf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
if (rawbuf)
rawbuf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
- }
+ }
if (rawbuf) {
buf[byteorder->byteorder.r] = rawbuf[byteorder->byteorder.r] * brightness;
buf[byteorder->byteorder.g] = rawbuf[byteorder->byteorder.g] * brightness;
@@ -94,15 +94,15 @@ void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_
}
}
-mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar) {
+mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar) {
mp_obj_t elems[len];
for (uint i = 0; i < len; i++) {
- elems[i] = pixelbuf_get_pixel(buf + (i * step), byteorder, dotstar);
+ elems[i] = pixelbuf_get_pixel(buf + ((i * slice_step) * step), byteorder, dotstar);
}
return mp_obj_new_tuple(len, elems);
}
-mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
+mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar) {
mp_obj_t elems[byteorder->bpp];
elems[0] = mp_obj_new_int(buf[byteorder->byteorder.r]);
diff --git a/shared-module/_pixelbuf/PixelBuf.h b/shared-module/_pixelbuf/PixelBuf.h
index 9e115fe0c..173ce61a8 100644
--- a/shared-module/_pixelbuf/PixelBuf.h
+++ b/shared-module/_pixelbuf/PixelBuf.h
@@ -42,9 +42,9 @@
#define DOTSTAR_GET_BRIGHTNESS(value) ((value & 0b00011111) / 31.0)
#define DOTSTAR_LED_START_FULL_BRIGHT 0xFF
-void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
-mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
-mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar);
-void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder);
+void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_details_t *byteorder, bool dotstar);
+mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_details_t *byteorder, bool dotstar);
+mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_details_t *byteorder, uint8_t step, mp_int_t slice_step, bool dotstar);
+void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_details_t *byteorder);
#endif
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/MP3Decoder.c
index f4861da36..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,
@@ -88,6 +91,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 +142,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;
}
@@ -124,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);
@@ -140,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) {
@@ -223,6 +282,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);
}
@@ -238,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) {
@@ -247,12 +306,14 @@ 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)) {
return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
}
@@ -279,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
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index 11db0f8ff..299c8ad35 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -308,10 +308,27 @@ STATIC void _refresh_display(displayio_display_obj_t* self) {
displayio_display_core_finish_refresh(&self->core);
}
+void common_hal_displayio_display_set_rotation(displayio_display_obj_t* self, int rotation){
+ bool transposed = (self->core.rotation == 90 || self->core.rotation == 270);
+ bool will_transposed = (rotation == 90 || rotation == 270);
+ if(transposed != will_transposed) {
+ int tmp = self->core.width;
+ self->core.width = self->core.height;
+ self->core.height = tmp;
+ }
+ displayio_display_core_set_rotation(&self->core, rotation);
+ supervisor_stop_terminal();
+ supervisor_start_terminal(self->core.width, self->core.height);
+ if (self->core.current_group != NULL) {
+ displayio_group_update_transform(self->core.current_group, &self->core.transform);
+ }
+}
+
uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self){
return self->core.rotation;
}
+
bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) {
if (!self->auto_refresh && !self->first_manual_refresh) {
uint64_t current_time = supervisor_ticks_ms64();
diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c
index 658daa8d6..120b70f76 100644
--- a/shared-module/displayio/display_core.c
+++ b/shared-module/displayio/display_core.c
@@ -86,6 +86,15 @@ void displayio_display_core_construct(displayio_display_core_t* self,
self->height = height;
self->ram_width = ram_width;
self->ram_height = ram_height;
+
+ displayio_display_core_set_rotation(self, rotation);
+}
+
+void displayio_display_core_set_rotation( displayio_display_core_t* self,
+ int rotation) {
+ int height = self->height;
+ int width = self->width;
+
rotation = rotation % 360;
self->rotation = rotation;
self->transform.x = 0;
diff --git a/shared-module/displayio/display_core.h b/shared-module/displayio/display_core.h
index 3a69cd40a..1c3d0f09c 100644
--- a/shared-module/displayio/display_core.h
+++ b/shared-module/displayio/display_core.h
@@ -68,6 +68,8 @@ uint16_t displayio_display_core_get_height(displayio_display_core_t* self);
void displayio_display_core_set_dither(displayio_display_core_t* self, bool dither);
bool displayio_display_core_get_dither(displayio_display_core_t* self);
+void displayio_display_core_set_rotation(displayio_display_core_t* self, int rotation);
+
bool displayio_display_core_bus_free(displayio_display_core_t *self);
bool displayio_display_core_begin_transaction(displayio_display_core_t* self);
void displayio_display_core_end_transaction(displayio_display_core_t* self);