diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 4c1993b7c4a6a..01dc1e4c90114 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -39,13 +39,16 @@ //| ======================================================== //| //| A .wav file prepped for audio playback. Only mono and stereo files are supported. Samples must -//| be 8 bit unsigned or 16 bit signed. +//| be 8 bit unsigned or 16 bit signed. If a buffer is provided, it will be used instead of allocating +//| an internal buffer. //| -//| .. class:: WaveFile(file) +//| .. class:: WaveFile(file[, buffer]) //| //| Load a .wav file for playback with `audioio.AudioOut` or `audiobusio.I2SOut`. //| //| :param typing.BinaryIO file: Already opened wave file +//| :param bytearray buffer: Optional pre-allocated buffer, that will be split in half and used for double-buffering of the data. If not provided, two 512 byte buffers are allocated internally. +//| //| //| Playing a wave file from flash:: //| @@ -68,15 +71,23 @@ //| print("stopped") //| 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) { - mp_arg_check_num(n_args, kw_args, 1, 1, false); + mp_arg_check_num(n_args, kw_args, 1, 2, false); audioio_wavefile_obj_t *self = m_new_obj(audioio_wavefile_obj_t); self->base.type = &audioio_wavefile_type; - if (MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) { - common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0])); - } else { + if (!MP_OBJ_IS_TYPE(args[0], &mp_type_fileio)) { mp_raise_TypeError(translate("file must be a file opened in byte mode")); } + uint8_t *buffer = NULL; + size_t buffer_size = 0; + if (n_args >= 2) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + buffer = bufinfo.buf; + buffer_size = bufinfo.len; + } + common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(args[0]), + buffer, buffer_size); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h index d2572318be748..f4a17231928b9 100644 --- a/shared-bindings/audiocore/WaveFile.h +++ b/shared-bindings/audiocore/WaveFile.h @@ -35,7 +35,7 @@ extern const mp_obj_type_t audioio_wavefile_type; void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self, - pyb_file_obj_t* file); + pyb_file_obj_t* file, uint8_t *buffer, size_t buffer_size); void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self); bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self); diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c index 810d9c33b4c6e..df5d4b61de4dc 100644 --- a/shared-module/audiocore/WaveFile.c +++ b/shared-module/audiocore/WaveFile.c @@ -46,7 +46,9 @@ struct wave_format_chunk { }; void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self, - pyb_file_obj_t* file) { + pyb_file_obj_t* file, + uint8_t *buffer, + size_t buffer_size) { // Load the wave self->file = file; uint8_t chunk_header[16]; @@ -84,7 +86,6 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self, } // Get the sample_rate self->sample_rate = format.sample_rate; - self->len = 256; self->channel_count = format.num_channels; self->bits_per_sample = format.bits_per_sample; @@ -111,21 +112,31 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t* self, // Try to allocate two buffers, one will be loaded from file and the other // DMAed to DAC. - self->buffer = m_malloc(self->len, false); - if (self->buffer == NULL) { - common_hal_audioio_wavefile_deinit(self); - mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer")); - } + if (buffer_size) { + self->len = buffer_size / 2; + self->buffer = buffer; + self->second_buffer = buffer + self->len; + } else { + self->len = 256; + self->buffer = m_malloc(self->len, false); + if (self->buffer == NULL) { + common_hal_audioio_wavefile_deinit(self); + mp_raise_msg(&mp_type_MemoryError, + translate("Couldn't allocate first buffer")); + } - self->second_buffer = m_malloc(self->len, false); - if (self->second_buffer == NULL) { - common_hal_audioio_wavefile_deinit(self); - mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer")); + self->second_buffer = m_malloc(self->len, false); + if (self->second_buffer == NULL) { + common_hal_audioio_wavefile_deinit(self); + mp_raise_msg(&mp_type_MemoryError, + translate("Couldn't allocate second buffer")); + } } } void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self) { self->buffer = NULL; + self->second_buffer = NULL; } bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self) {