Skip to content

Commit f878bc4

Browse files
committed
atmel-samd: Fix AudioOut buffer playback by supporting bytes_per_sample.
Thanks to @ntoll for finding this bug!
1 parent 5e231bd commit f878bc4

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
@@ -104,6 +104,7 @@ void audioout_reset(void) {
104104
void audioout_background(void) {
105105
if (MP_STATE_VM(audioout_block_counter) != NULL &&
106106
active_audioout != NULL &&
107+
active_audioout->second_buffer != NULL &&
107108
active_audioout->last_loaded_block < tc_get_count_value(MP_STATE_VM(audioout_block_counter))) {
108109
uint8_t* buffer;
109110
if (tc_get_count_value(MP_STATE_VM(audioout_block_counter)) % 2 == 1) {
@@ -133,6 +134,7 @@ void audioout_background(void) {
133134
descriptor = active_audioout->second_descriptor;
134135
}
135136
descriptor->BTCNT.reg = length_read / active_audioout->bytes_per_sample;
137+
descriptor->SRCADDR.reg = ((uint32_t) buffer) + length_read;
136138
descriptor->DESCADDR.reg = 0;
137139
}
138140
}
@@ -349,7 +351,8 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
349351
void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* self,
350352
const mcu_pin_obj_t* pin,
351353
uint16_t* buffer,
352-
uint32_t len) {
354+
uint32_t len,
355+
uint8_t bytes_per_sample) {
353356
self->pin = pin;
354357
if (pin != &pin_PA02) {
355358
mp_raise_ValueError("Invalid pin");
@@ -361,8 +364,8 @@ void common_hal_audioio_audioout_construct_from_buffer(audioio_audioout_obj_t* s
361364

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

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy