From 9eadda68b878e6c40bd5b20c623885150b63b3b0 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 20 Jun 2017 11:18:46 -0700 Subject: [PATCH] atmel-samd: Fix AudioOut buffer playback by supporting bytes_per_sample. Thanks to @ntoll for finding this bug! --- atmel-samd/common-hal/audioio/AudioOut.c | 9 ++++++--- shared-bindings/audioio/AudioOut.c | 18 +++++++++++------- shared-bindings/audioio/AudioOut.h | 6 ++++-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/atmel-samd/common-hal/audioio/AudioOut.c b/atmel-samd/common-hal/audioio/AudioOut.c index 9fb1a6ebed..c0ccd547e3 100644 --- a/atmel-samd/common-hal/audioio/AudioOut.c +++ b/atmel-samd/common-hal/audioio/AudioOut.c @@ -103,6 +103,7 @@ void audioout_reset(void) { void audioout_background(void) { if (MP_STATE_VM(audioout_block_counter) != NULL && active_audioout != NULL && + active_audioout->second_buffer != NULL && active_audioout->last_loaded_block < tc_get_count_value(MP_STATE_VM(audioout_block_counter))) { uint8_t* buffer; if (tc_get_count_value(MP_STATE_VM(audioout_block_counter)) % 2 == 1) { @@ -132,6 +133,7 @@ void audioout_background(void) { descriptor = active_audioout->second_descriptor; } descriptor->BTCNT.reg = length_read / active_audioout->bytes_per_sample; + descriptor->SRCADDR.reg = ((uint32_t) buffer) + length_read; descriptor->DESCADDR.reg = 0; } } @@ -348,7 +350,8 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t* void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t* buffer, - uint32_t len) { + uint32_t len, + uint8_t bytes_per_sample) { self->pin = pin; if (pin != &pin_PA02) { mp_raise_ValueError("Invalid pin"); @@ -360,8 +363,8 @@ void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* s self->buffer = (uint8_t*) buffer; self->second_buffer = NULL; - // Input len is a count. Internal len is in bytes. - self->len = 2 * len; + self->bytes_per_sample = bytes_per_sample; + self->len = len; self->frequency = 8000; } diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index b476521046..56c307a4ff 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -27,6 +27,7 @@ #include #include "lib/utils/context_manager_helpers.h" +#include "py/binary.h" #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" @@ -62,11 +63,11 @@ //| //| # Generate one period of sine wav. //| length = 8000 // 440 -//| b = array.array("H", [0] * length) +//| sine_wave = array.array("H", [0] * length) //| for i in range(length): -//| b[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) +//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) //| -//| sample = audioio.AudioOut(board.SPEAKER, sin_wave) +//| sample = audioio.AudioOut(board.SPEAKER, sine_wave) //| sample.play(loop=True) //| time.sleep(1) //| sample.stop() @@ -106,12 +107,15 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar if (MP_OBJ_IS_TYPE(args[1], &fatfs_type_fileio)) { common_hal_audioio_audioout_construct_from_file(self, pin, MP_OBJ_TO_PTR(args[1])); } else if (mp_get_buffer(args[1], &bufinfo, MP_BUFFER_READ)) { - if (bufinfo.len % 2 == 1) { - mp_raise_ValueError("sample_source must be an even number of bytes (two per sample)"); + uint8_t bytes_per_sample = 1; + if (bufinfo.typecode == 'H') { + bytes_per_sample = 2; + } else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) { + mp_raise_ValueError("sample_source buffer must be a bytearray or array of type 'H' or 'B'"); } - common_hal_audioio_audioout_construct_from_buffer(self, pin, ((uint16_t*)bufinfo.buf), bufinfo.len / 2); + common_hal_audioio_audioout_construct_from_buffer(self, pin, ((uint16_t*)bufinfo.buf), bufinfo.len, bytes_per_sample); } else { - mp_raise_TypeError("sample_source must be a file or bytes-like object."); + mp_raise_TypeError("sample_source must be a file or bytes-like object"); } return MP_OBJ_FROM_PTR(self); diff --git a/shared-bindings/audioio/AudioOut.h b/shared-bindings/audioio/AudioOut.h index 5227921172..0fb289e2d6 100644 --- a/shared-bindings/audioio/AudioOut.h +++ b/shared-bindings/audioio/AudioOut.h @@ -33,8 +33,10 @@ extern const mp_obj_type_t audioio_audioout_type; -void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t* buffer, uint32_t len); -void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* self, const mcu_pin_obj_t* pin, pyb_file_obj_t* file); +void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self, + const mcu_pin_obj_t* pin, uint16_t* buffer, uint32_t len, uint8_t bytes_per_sample); +void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* self, + const mcu_pin_obj_t* pin, pyb_file_obj_t* file); void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self); void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop);