Skip to content

Commit 9907e3f

Browse files
committed
Allow to specify pre-allocated buffer in audicore.WaveFile
It lets us re-use the same buffer for playing multiple files. This also allows us to control the size of the buffer. Half of the buffer will be used for the fist, and half for the second internal buffer.
1 parent 347fbb6 commit 9907e3f

3 files changed

Lines changed: 39 additions & 18 deletions

File tree

shared-bindings/audiocore/WaveFile.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@
3939
//| ========================================================
4040
//|
4141
//| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must
42-
//| be 8 bit unsigned or 16 bit signed.
42+
//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating
43+
//| an internal buffer.
4344
//|
44-
//| .. class:: WaveFile(file)
45+
//| .. class:: WaveFile(file[, buffer])
4546
//|
4647
//| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`.
4748
//|
4849
//| :param typing.BinaryIO file: Already opened wave file
50+
//| :param bytearray buffer: Optional pre-allocated buffer
4951
//|
5052
//| Playing a wave file from flash::
5153
//|
@@ -68,15 +70,23 @@
6870
//| print("stopped")
6971
//|
7072
STATIC mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
71-
mp_arg_check_num(n_args, kw_args, 1, 1, false);
73+
mp_arg_check_num(n_args, kw_args, 1, 2, false);
7274

7375
audioio_wavefile_obj_t *self = m_new_obj(audioio_wavefile_obj_t);
7476
self->base.type = &audioio_wavefile_type;
75-
if (MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
76-
common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]));
77-
} else {
77+
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) {
7878
mp_raise_TypeError(translate("file must be a file opened in byte mode"));
7979
}
80+
uint8_t *buffer = NULL;
81+
size_t buffer_size = 0;
82+
if (n_args >= 2) {
83+
mp_buffer_info_t bufinfo;
84+
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
85+
buffer = bufinfo.buf;
86+
buffer_size = bufinfo.len;
87+
}
88+
common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]),
89+
buffer, buffer_size);
8090

8191
return MP_OBJ_FROM_PTR(self);
8292
}

shared-bindings/audiocore/WaveFile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
extern const mp_obj_type_t audioio_wavefile_type;
3636

3737
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
38-
pyb_file_obj_t* file);
38+
pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size);
3939

4040
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self);
4141
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self);

shared-module/audiocore/WaveFile.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ struct wave_format_chunk {
4646
};
4747

4848
void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
49-
pyb_file_obj_t* file) {
49+
pyb_file_obj_t* file,
50+
uint8_t *buffer,
51+
size_t buffer_size) {
5052
// Load the wave
5153
self->file = file;
5254
uint8_t chunk_header[16];
@@ -84,7 +86,6 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
8486
}
8587
// Get the sample_rate
8688
self->sample_rate = format.sample_rate;
87-
self->len = 256;
8889
self->channel_count = format.num_channels;
8990
self->bits_per_sample = format.bits_per_sample;
9091

@@ -111,21 +112,31 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self,
111112

112113
// Try to allocate two buffers, one will be loaded from file and the other
113114
// DMAed to DAC.
114-
self->buffer = m_malloc(self->len, false);
115-
if (self->buffer == NULL) {
116-
common_hal_audioio_wavefile_deinit(self);
117-
mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer"));
118-
}
115+
if (buffer_size) {
116+
self->len = buffer_size / 2;
117+
self->buffer = buffer;
118+
self->second_buffer = buffer + self->len;
119+
} else {
120+
self->len = 256;
121+
self->buffer = m_malloc(self->len, false);
122+
if (self->buffer == NULL) {
123+
common_hal_audioio_wavefile_deinit(self);
124+
mp_raise_msg(&mp_type_MemoryError,
125+
translate("Couldn't allocate first buffer"));
126+
}
119127

120-
self->second_buffer = m_malloc(self->len, false);
121-
if (self->second_buffer == NULL) {
122-
common_hal_audioio_wavefile_deinit(self);
123-
mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer"));
128+
self->second_buffer = m_malloc(self->len, false);
129+
if (self->second_buffer == NULL) {
130+
common_hal_audioio_wavefile_deinit(self);
131+
mp_raise_msg(&mp_type_MemoryError,
132+
translate("Couldn't allocate second buffer"));
133+
}
124134
}
125135
}
126136

127137
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self) {
128138
self->buffer = NULL;
139+
self->second_buffer = NULL;
129140
}
130141

131142
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self) {

0 commit comments

Comments
 (0)