8000 atmel-samd: Fix AudioOut buffer playback by supporting bytes_per_sample. · sparkfun/circuitpython@9eadda6 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9eadda6

Browse files
committed
atmel-samd: Fix AudioOut buffer playback by supporting bytes_per_sample.
Thanks to @ntoll for finding this bug!
1 parent 97fcdfb commit 9eadda6

File tree

3 files changed

+21
-12
lines changed

3 files changed

+21
-12
lines changed

atmel-samd/common-hal/audioio/AudioOut.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ void audioout_reset(void) {
103103
void audioout_background(void) {
104104
if (MP_STATE_VM(audioout_block_counter) != NULL &&
105105
active_audioout != NULL &&
106+
active_audioout->second_buffer != NULL &&
106107
active_audioout->last_loaded_block < tc_get_count_value(MP_STATE_VM(audioout_block_counter))) {
107108
uint8_t* buffer;
108109
if (tc_get_count_value(MP_STATE_VM(audioout_block_counter)) % 2 == 1) {
@@ -132,6 +133,7 @@ void audioout_background(void) {
132133
descriptor = active_audioout->second_descriptor;
133134
}
134135
descriptor->BTCNT.reg = length_read / active_audioout->bytes_per_sample;
136+
descriptor->SRCADDR.reg = ((uint32_t) buffer) + length_read;
135137
descriptor->DESCADDR.reg = 0;
136138
}
137139
}
@@ -348,7 +350,8 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
348350
void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self,
349351
const mcu_pin_obj_t* pin,
350352
uint16_t* buffer,
351-
uint32_t len) {
353+
uint32_t len,
354+
uint8_t bytes_per_sample) {
352355
self->pin = pin;
353356
if (pin != &pin_PA02) {
354357
mp_raise_ValueError("Invalid pin");
@@ -360,8 +363,8 @@ void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* s
360363

361364
self->buffer = (uint8_t*) buffer;
362365
self->second_buffer = NULL;
363-
// Input len is a count. Internal len is in bytes.
364-
self->len = 2 * len;
366+
self->bytes_per_sample = bytes_per_sample;
367+
self->len = len;
365368
self->frequency = 8000;
366369
}
367370

shared-bindings/audioio/AudioOut.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <stdint.h>
2828

2929
#include "lib/utils/context_manager_helpers.h"
30+
#include "py/binary.h"
3031
#include "py/objproperty.h"
3132
#include "py/runtime.h"
3233
#include "shared-bindings/microcontroller/Pin.h"
@@ -62,11 +63,11 @@
6263
//|
6364
//| # Generate one period of sine wav.
6465
//| length = 8000 // 440
65-
//| b = array.array("H", [0] * length)
66+
//| sine_wave = array.array("H", [0] * length)
6667
//| for i in range(length):
67-
//| b[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
68+
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / 18) * (2 ** 15) + 2 ** 15)
6869
//|
69-
//| sample = audioio.AudioOut(board.SPEAKER, sin_wave)
70+
//| sample = audioio.AudioOut(board.SPEAKER, sine_wave)
7071
//| sample.play(loop=True)
7172
//| time.sleep(1)
7273
//| sample.stop()
@@ -106,12 +107,15 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar
106107
if (MP_OBJ_IS_TYPE(args[1], &fatfs_type_fileio)) {
107108
common_hal_audioio_audioout_construct_from_file(self, pin, MP_OBJ_TO_PTR(args[1]));
108109
} else if (mp_get_buffer(args[1], &bufinfo, MP_BUFFER_READ)) {
109-
if (bufinfo.len % 2 == 1) {
110-
mp_raise_ValueError("sample_source must be an even number of bytes (two per sample)");
110+
uint8_t bytes_per_sample = 1;
111+
if (bufinfo.typecode == 'H') {
112+
bytes_per_sample = 2;
113+
} else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE) {
114+
mp_raise_ValueError("sample_source buffer must be a bytearray or array of type 'H' or 'B'");
111115
}
112-
common_hal_audioio_audioout_construct_from_buffer(self, pin, ((uint16_t*)bufinfo.buf), bufinfo.len / 2);
116+
common_hal_audioio_audioout_construct_from_buffer(self, pin, ((uint16_t*)bufinfo.buf), bufinfo.len, bytes_per_sample);
113117
} else {
114-
mp_raise_TypeError("sample_source must be a file or bytes-like object.");
118+
mp_raise_TypeError("sample_source must be a file or bytes-like object");
115119
}
116120

117121
return MP_OBJ_FROM_PTR(self);

shared-bindings/audioio/AudioOut.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@
3333

3434
extern const mp_obj_type_t audioio_audioout_type;
3535

36-
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);
37-
void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* self, const mcu_pin_obj_t* pin, pyb_file_obj_t* file);
36+
void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self,
37+
const mcu_pin_obj_t* pin, uint16_t* buffer, uint32_t len, uint8_t bytes_per_sample);
38+
void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* self,
39+
const mcu_pin_obj_t* pin, pyb_file_obj_t* file);
3840

3941
void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self);
4042
void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop);

0 commit comments

Comments
 (0)
0