From 39df7ca4a88e71a4003a5a869d6575804df8d08e Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 13:25:05 -0600 Subject: [PATCH 1/9] Initial pitch shift effect implementation. --- .../unix/variants/coverage/mpconfigvariant.mk | 2 + py/circuitpy_defns.mk | 1 + shared-bindings/audiodelays/PitchShift.c | 261 +++++++++++++ shared-bindings/audiodelays/PitchShift.h | 33 ++ shared-bindings/audiodelays/__init__.c | 2 + shared-module/audiodelays/PitchShift.c | 347 ++++++++++++++++++ shared-module/audiodelays/PitchShift.h | 58 +++ 7 files changed, 704 insertions(+) create mode 100644 shared-bindings/audiodelays/PitchShift.c create mode 100644 shared-bindings/audiodelays/PitchShift.h create mode 100644 shared-module/audiodelays/PitchShift.c create mode 100644 shared-module/audiodelays/PitchShift.h diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 96dfcd68bcc3e..94a246e0199b0 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -34,6 +34,7 @@ SRC_BITMAP := \ shared-bindings/audiocore/RawSample.c \ shared-bindings/audiocore/WaveFile.c \ shared-bindings/audiodelays/Echo.c \ + shared-bindings/audiodelays/PitchShift.c \ shared-bindings/audiodelays/__init__.c \ shared-bindings/audiofilters/Distortion.c \ shared-bindings/audiofilters/Filter.c \ @@ -77,6 +78,7 @@ SRC_BITMAP := \ shared-module/audiocore/RawSample.c \ shared-module/audiocore/WaveFile.c \ shared-module/audiodelays/Echo.c \ + shared-module/audiodelays/PitchShift.c \ shared-module/audiodelays/__init__.c \ shared-module/audiofilters/Distortion.c \ shared-module/audiofilters/Filter.c \ diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index f4335f4b2ae5e..fc542c79662a1 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -624,6 +624,7 @@ SRC_SHARED_MODULE_ALL = \ audiocore/WaveFile.c \ audiocore/__init__.c \ audiodelays/Echo.c \ + audiodelays/PitchShift.c \ audiodelays/__init__.c \ audiofilters/Distortion.c \ audiofilters/Filter.c \ diff --git a/shared-bindings/audiodelays/PitchShift.c b/shared-bindings/audiodelays/PitchShift.c new file mode 100644 index 0000000000000..df2189945aa5d --- /dev/null +++ b/shared-bindings/audiodelays/PitchShift.c @@ -0,0 +1,261 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiodelays/PitchShift.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiodelays/PitchShift.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class PitchShift: +//| """A pitch shift effect""" +//| +//| def __init__( +//| self, +//| semitones: synthio.BlockInput = 0.0, +//| mix: synthio.BlockInput = 1.0, +//| window: int = 1024, +//| overlap: int = 128, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a pitch shift effect where the original sample play back is altered to change the +//| the perceived pitch by a factor of semi-tones (1/12th of an octave). This effect will cause +//| a slight delay in the output depending on the size of the window and overlap buffers. +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param synthio.BlockInput semitones: The amount of pitch shifting in semitones (1/12th of an octave) +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0) +//| :param int window: The total size in bytes of the window buffer used alter the playback pitch +//| :param int overlap: The total size in bytes of the overlap buffer used to prevent popping in the output. If set as 0, no overlap will be used. +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Shifting the pitch of a synth by 5 semitones:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiodelays +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP0, word_select=board.GP1, data=board.GP2) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| pitch_shift = audiodelays.PitchShift(semitones=5.0, mix=0.5, window=2048, overlap=256, buffer_size=1024, channel_count=1, sample_rate=44100) +//| pitch_shift.play(synth) +//| audio.play(pitch_shift) +//| +//| while True: +//| for notenum in (60, 64, 67, 71): +//| synth.press(notenum) +//| time.sleep(0.25) +//| synth.release_all()""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_semitones, ARG_mix, ARG_window, ARG_overlap, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_semitones, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0)} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1)} }, + { MP_QSTR_window, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} }, + { MP_QSTR_overlap, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 128} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiodelays_pitch_shift_obj_t *self = mp_obj_malloc(audiodelays_pitch_shift_obj_t, &audiodelays_pitch_shift_type); + common_hal_audiodelays_pitch_shift_construct(self, args[ARG_semitones].u_obj, args[ARG_mix].u_obj, args[ARG_window].u_int, args[ARG_overlap].u_int, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + + +//| def deinit(self) -> None: +//| """Deinitialises the PitchShift.""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_deinit(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_deinit_obj, audiodelays_pitch_shift_deinit); + +static void check_for_deinit(audiodelays_pitch_shift_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + + +//| def __enter__(self) -> PitchShift: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_audiodelays_pitch_shift_deinit(args[0]); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiodelays_pitch_shift___exit___obj, 4, 4, audiodelays_pitch_shift_obj___exit__); + + +//| semitones: synthio.BlockInput +//| """The amount of pitch shifting in semitones (1/12th of an octave).""" +//| +static mp_obj_t audiodelays_pitch_shift_obj_get_semitones(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_audiodelays_pitch_shift_get_semitones(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_semitones_obj, audiodelays_pitch_shift_obj_get_semitones); + +static mp_obj_t audiodelays_pitch_shift_obj_set_semitones(mp_obj_t self_in, mp_obj_t semitones_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_set_semitones(self, semitones_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_pitch_shift_set_semitones_obj, audiodelays_pitch_shift_obj_set_semitones); + +MP_PROPERTY_GETSET(audiodelays_pitch_shift_semitones_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_semitones_obj, + (mp_obj_t)&audiodelays_pitch_shift_set_semitones_obj); + + +//| mix: synthio.BlockInput +//| """The output mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiodelays_pitch_shift_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiodelays_pitch_shift_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_mix_obj, audiodelays_pitch_shift_obj_get_mix); + +static mp_obj_t audiodelays_pitch_shift_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_pitch_shift_set_mix_obj, audiodelays_pitch_shift_obj_set_mix); + +MP_PROPERTY_GETSET(audiodelays_pitch_shift_mix_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_mix_obj, + (mp_obj_t)&audiodelays_pitch_shift_set_mix_obj); + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiodelays_pitch_shift_obj_get_playing(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiodelays_pitch_shift_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_playing_obj, audiodelays_pitch_shift_obj_get_playing); + +MP_PROPERTY_GETTER(audiodelays_pitch_shift_playing_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_playing_obj); + + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor.""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiodelays_pitch_shift_play(self, sample, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_pitch_shift_play_obj, 1, audiodelays_pitch_shift_obj_play); + + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiodelays_pitch_shift_obj_stop(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_stop_obj, audiodelays_pitch_shift_obj_stop); + + +static const mp_rom_map_elem_t audiodelays_pitch_shift_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_pitch_shift_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiodelays_pitch_shift___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_pitch_shift_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_pitch_shift_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_pitch_shift_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_semitones), MP_ROM_PTR(&audiodelays_pitch_shift_semitones_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_pitch_shift_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiodelays_pitch_shift_locals_dict, audiodelays_pitch_shift_locals_dict_table); + +static const audiosample_p_t audiodelays_pitch_shift_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiodelays_pitch_shift_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiodelays_pitch_shift_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiodelays_pitch_shift_type, + MP_QSTR_PitchShift, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiodelays_pitch_shift_make_new, + locals_dict, &audiodelays_pitch_shift_locals_dict, + protocol, &audiodelays_pitch_shift_proto + ); diff --git a/shared-bindings/audiodelays/PitchShift.h b/shared-bindings/audiodelays/PitchShift.h new file mode 100644 index 0000000000000..018ef150cf7e5 --- /dev/null +++ b/shared-bindings/audiodelays/PitchShift.h @@ -0,0 +1,33 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiodelays/PitchShift.h" + +extern const mp_obj_type_t audiodelays_pitch_shift_type; + +void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t *self, + mp_obj_t semitones, mp_obj_t mix, uint32_t window, uint32_t overlap, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self); +bool common_hal_audiodelays_pitch_shift_deinited(audiodelays_pitch_shift_obj_t *self); + +uint32_t common_hal_audiodelays_pitch_shift_get_sample_rate(audiodelays_pitch_shift_obj_t *self); +uint8_t common_hal_audiodelays_pitch_shift_get_channel_count(audiodelays_pitch_shift_obj_t *self); +uint8_t common_hal_audiodelays_pitch_shift_get_bits_per_sample(audiodelays_pitch_shift_obj_t *self); + +mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t semitones); + +mp_obj_t common_hal_audiodelays_pitch_shift_get_mix(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_set_mix(audiodelays_pitch_shift_obj_t *self, mp_obj_t arg); + +bool common_hal_audiodelays_pitch_shift_get_playing(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_play(audiodelays_pitch_shift_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiodelays_pitch_shift_stop(audiodelays_pitch_shift_obj_t *self); diff --git a/shared-bindings/audiodelays/__init__.c b/shared-bindings/audiodelays/__init__.c index 4b0be7b75ad86..58cb9dc70a879 100644 --- a/shared-bindings/audiodelays/__init__.c +++ b/shared-bindings/audiodelays/__init__.c @@ -11,6 +11,7 @@ #include "shared-bindings/audiodelays/__init__.h" #include "shared-bindings/audiodelays/Echo.h" +#include "shared-bindings/audiodelays/PitchShift.h" //| """Support for audio delay effects //| @@ -21,6 +22,7 @@ static const mp_rom_map_elem_t audiodelays_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiodelays) }, { MP_ROM_QSTR(MP_QSTR_Echo), MP_ROM_PTR(&audiodelays_echo_type) }, + { MP_ROM_QSTR(MP_QSTR_PitchShift), MP_ROM_PTR(&audiodelays_pitch_shift_type) }, }; static MP_DEFINE_CONST_DICT(audiodelays_module_globals, audiodelays_module_globals_table); diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c new file mode 100644 index 0000000000000..683dbb28a4e97 --- /dev/null +++ b/shared-module/audiodelays/PitchShift.c @@ -0,0 +1,347 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiodelays/PitchShift.h" + +#include +#include "py/runtime.h" +#include + +void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t *self, + mp_obj_t semitones, mp_obj_t mix, uint32_t window, uint32_t overlap, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the effect's starting values. + + synthio_block_assign_slot(semitones, &self->semitones, MP_QSTR_semitones); + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + // Allocate the window buffer + self->window_len = window; // bytes + self->window_buffer = m_malloc(self->window_len); + if (self->window_buffer == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->window_len); + } + memset(self->window_buffer, 0, self->window_len); + + // Allocate the overlap buffer + self->overlap_len = overlap; // bytes + if (self->overlap_len) { + self->overlap_buffer = m_malloc(self->overlap_len); + if (self->overlap_buffer == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->overlap_len); + } + memset(self->overlap_buffer, 0, self->overlap_len); + } else { + self->overlap_buffer = NULL; + } + + // The current position that the end of the overlap buffer will be written to the window buffer + self->window_index = 0; + + // The position that the current sample will be written to the overlap buffer + self->overlap_index = 0; + + // The position that the window buffer will be read from and written to the output + self->read_index = 0; + + // Calculate the rate to increment the read index + mp_float_t f_semitones = synthio_block_slot_get(&self->semitones); + recalculate_rate(self, f_semitones); +} + +bool common_hal_audiodelays_pitch_shift_deinited(audiodelays_pitch_shift_obj_t *self) { + if (self->window_buffer == NULL) { + return true; + } + return false; +} + +void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self) { + if (common_hal_audiodelays_pitch_shift_deinited(self)) { + return; + } + self->window_buffer = NULL; + self->overlap_buffer = NULL; + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self) { + return self->semitones.obj; +} + +void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t delay_ms) { + synthio_block_assign_slot(delay_ms, &self->semitones, MP_QSTR_semitones); + mp_float_t semitones = synthio_block_slot_get(&self->semitones); + recalculate_rate(self, semitones); +} + +void recalculate_rate(audiodelays_pitch_shift_obj_t *self, mp_float_t semitones) { + self->read_rate = (uint32_t)(MICROPY_FLOAT_C_FUN(pow)(2.0, semitones / MICROPY_FLOAT_CONST(12.0)) * (1 << PITCH_READ_SHIFT)); + self->current_semitones = semitones; +} + +mp_obj_t common_hal_audiodelays_pitch_shift_get_mix(audiodelays_pitch_shift_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiodelays_pitch_shift_set_mix(audiodelays_pitch_shift_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +void audiodelays_pitch_shift_reset_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->window_buffer, 0, self->window_len); + if (self->overlap_len) { + memset(self->overlap_buffer, 0, self->overlap_len); + } +} + +bool common_hal_audiodelays_pitch_shift_get_playing(audiodelays_pitch_shift_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiodelays_pitch_shift_play(audiodelays_pitch_shift_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiodelays_pitch_shift_stop(audiodelays_pitch_shift_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch_shift_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // The window and overlap buffers are always stored as a 16-bit value internally + int16_t *window_buffer = (int16_t *)self->window_buffer; + uint32_t window_size = self->window_len / sizeof(uint16_t) / self->base.channel_count; + + int16_t *overlap_buffer = NULL; + uint32_t overlap_size = 0; + if (self->overlap_len) { + overlap_buffer = (int16_t *)self->overlap_buffer; + overlap_size = self->overlap_len / sizeof(uint16_t) / self->base.channel_count; + } + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + if (self->sample == NULL) { + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + memset(word_buffer, 32768, length * (self->base.bits_per_sample / 8)); + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + + // tick all block inputs + shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count); + (void)synthio_block_slot_get(&self->semitones); + (void)synthio_block_slot_get(&self->mix); + + length = 0; + } else { + // we have a sample to play and apply effect + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t semitones = synthio_block_slot_get(&self->semitones); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + // Only recalculate rate if semitones has changes + if (memcmp(&semitones, &self->current_semitones, sizeof(mp_float_t))) { + recalculate_rate(self, semitones); + } + + for (uint32_t i = 0; i < n; i++) { + bool buf_offset = (channel == 1 || i % self->base.channel_count == 1); + + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + if (self->overlap_len) { + // Copy last sample from overlap and store in buffer + window_buffer[self->window_index + window_size * buf_offset] = overlap_buffer[self->overlap_index + overlap_size * buf_offset]; + + // Save current sample in overlap + overlap_buffer[self->overlap_index + overlap_size * buf_offset] = (int16_t)sample_word; + } else { + // Write sample to buffer + window_buffer[self->window_index + window_size * buf_offset] = (int16_t)sample_word; + } + + // Determine how far we are into the overlap + uint32_t read_index = self->read_index >> PITCH_READ_SHIFT; + uint32_t read_overlap_offset = read_index + window_size * (read_index < self->window_index) - self->window_index; + + // Read sample from buffer + int32_t word = (int32_t)window_buffer[self->read_index + window_size * buf_offset]; + + // Check if we're within the overlap range and mix buffer sample with overlap sample + if (read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { + // Apply volume based on overlap position to buffer sample + word *= (int32_t)read_overlap_offset; + + // Add overlap with volume based on overlap position + word += (int32_t)overlap_buffer[((self->overlap_index + read_overlap_offset) % overlap_size) + overlap_size * buf_offset] * (int32_t)(overlap_size - read_overlap_offset); + + // Scale down + word /= (int32_t)overlap_size; + } + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t mixed = (int8_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + if (self->base.samples_signed) { + hword_buffer[i] = mixed; + } else { + hword_buffer[i] = (uint8_t)mixed ^ 0x80; + } + } + + // Increment window buffer write pointer + self->window_index++; + if (self->window_index >= window_size) self->window_index = 0; + + // Increment overlap buffer pointer + if (self->overlap_len) { + self->overlap_index++; + if (self->overlap_index >= overlap_size) self->overlap_index = 0; + } + + // Increment window buffer read pointer by rate + self->read_index += self->read_rate; + if (self->read_index >= window_size << PITCH_READ_SHIFT) self->read_index -= window_size << PITCH_READ_SHIFT; + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // PitchShift always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiodelays/PitchShift.h b/shared-module/audiodelays/PitchShift.h new file mode 100644 index 0000000000000..dddcfa4efc019 --- /dev/null +++ b/shared-module/audiodelays/PitchShift.h @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +#define PITCH_READ_SHIFT (8) + +extern const mp_obj_type_t audiodelays_pitch_shift_type; + +typedef struct { + audiosample_base_t base; + synthio_block_slot_t semitones; + mp_float_t current_semitones; + synthio_block_slot_t mix; + uint32_t window_len; + uint32_t overlap_len; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int8_t *window_buffer; + uint32_t window_index; // words + + int8_t *overlap_buffer; + uint32_t overlap_index; // words + + uint32_t read_index; // words << PITCH_READ_SHIFT + uint32_t read_rate; // words << PITCH_READ_SHIFT + + mp_obj_t sample; +} audiodelays_pitch_shift_obj_t; + +void recalculate_rate(audiodelays_pitch_shift_obj_t *self, mp_float_t semitones); + +void audiodelays_pitch_shift_reset_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes From ec428b773596dca481983363a220b7c1e8472b31 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 21:09:28 -0600 Subject: [PATCH 2/9] Fix read index bug. --- shared-module/audiodelays/PitchShift.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index 683dbb28a4e97..d12099c0e969a 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -286,7 +286,7 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch uint32_t read_overlap_offset = read_index + window_size * (read_index < self->window_index) - self->window_index; // Read sample from buffer - int32_t word = (int32_t)window_buffer[self->read_index + window_size * buf_offset]; + int32_t word = (int32_t)window_buffer[read_index + window_size * buf_offset]; // Check if we're within the overlap range and mix buffer sample with overlap sample if (read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { From 9fbb39df9371b22773727c933dfbb3509d1862fd Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 21:09:53 -0600 Subject: [PATCH 3/9] Improve index incrementing. --- shared-module/audiodelays/PitchShift.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index d12099c0e969a..4d52bb66d37ab 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -313,20 +313,22 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch hword_buffer[i] = (uint8_t)mixed ^ 0x80; } } + + if (self->base.channel_count == 1 || buf_offset) { + // Increment window buffer write pointer + self->window_index++; + if (self->window_index >= window_size) self->window_index = 0; + + // Increment overlap buffer pointer + if (overlap_size) { + self->overlap_index++; + if (self->overlap_index >= overlap_size) self->overlap_index = 0; + } - // Increment window buffer write pointer - self->window_index++; - if (self->window_index >= window_size) self->window_index = 0; - - // Increment overlap buffer pointer - if (self->overlap_len) { - self->overlap_index++; - if (self->overlap_index >= overlap_size) self->overlap_index = 0; + // Increment window buffer read pointer by rate + self->read_index += self->read_rate; + if (self->read_index >= window_size << PITCH_READ_SHIFT) self->read_index -= window_size << PITCH_READ_SHIFT; } - - // Increment window buffer read pointer by rate - self->read_index += self->read_rate; - if (self->read_index >= window_size << PITCH_READ_SHIFT) self->read_index -= window_size << PITCH_READ_SHIFT; } // Update the remaining length and the buffer positions based on how much we wrote into our buffer From 96d21f981c0aa06cb8f17d7b7d7b7a3ac3d58a31 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 21:10:13 -0600 Subject: [PATCH 4/9] Fix bug when overlap_size = 0. --- shared-module/audiodelays/PitchShift.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index 4d52bb66d37ab..b65ef57261b44 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -270,7 +270,7 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch } } - if (self->overlap_len) { + if (overlap_size) { // Copy last sample from overlap and store in buffer window_buffer[self->window_index + window_size * buf_offset] = overlap_buffer[self->overlap_index + overlap_size * buf_offset]; @@ -289,7 +289,7 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch int32_t word = (int32_t)window_buffer[read_index + window_size * buf_offset]; // Check if we're within the overlap range and mix buffer sample with overlap sample - if (read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { + if (overlap_size && read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { // Apply volume based on overlap position to buffer sample word *= (int32_t)read_overlap_offset; From 60e7786b8c2aa00ab37335865b5c32b4ac4f0d15 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 21:42:34 -0600 Subject: [PATCH 5/9] Implement different mixing scheme. --- shared-module/audiodelays/PitchShift.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index b65ef57261b44..60793ee494e91 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -248,7 +248,7 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); mp_float_t semitones = synthio_block_slot_get(&self->semitones); - mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); // Only recalculate rate if semitones has changes if (memcmp(&semitones, &self->current_semitones, sizeof(mp_float_t))) { @@ -300,13 +300,16 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch word /= (int32_t)overlap_size; } + word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) + (word * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + if (MP_LIKELY(self->base.bits_per_sample == 16)) { - word_buffer[i] = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + word_buffer[i] = (int16_t)word; if (!self->base.samples_signed) { word_buffer[i] ^= 0x8000; } } else { - int8_t mixed = (int8_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + int8_t mixed = (int8_t)word; if (self->base.samples_signed) { hword_buffer[i] = mixed; } else { From d1bf3f927ffa241f99919f8ffc2855a87bf33fd8 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 11 Feb 2025 21:52:24 -0600 Subject: [PATCH 6/9] Pre-commit formatting fix. --- shared-module/audiodelays/PitchShift.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index 60793ee494e91..cd50e6cda94a6 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -287,7 +287,7 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch // Read sample from buffer int32_t word = (int32_t)window_buffer[read_index + window_size * buf_offset]; - + // Check if we're within the overlap range and mix buffer sample with overlap sample if (overlap_size && read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { // Apply volume based on overlap position to buffer sample @@ -316,21 +316,27 @@ audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch hword_buffer[i] = (uint8_t)mixed ^ 0x80; } } - + if (self->base.channel_count == 1 || buf_offset) { // Increment window buffer write pointer self->window_index++; - if (self->window_index >= window_size) self->window_index = 0; + if (self->window_index >= window_size) { + self->window_index = 0; + } // Increment overlap buffer pointer if (overlap_size) { self->overlap_index++; - if (self->overlap_index >= overlap_size) self->overlap_index = 0; + if (self->overlap_index >= overlap_size) { + self->overlap_index = 0; + } } // Increment window buffer read pointer by rate self->read_index += self->read_rate; - if (self->read_index >= window_size << PITCH_READ_SHIFT) self->read_index -= window_size << PITCH_READ_SHIFT; + if (self->read_index >= window_size << PITCH_READ_SHIFT) { + self->read_index -= window_size << PITCH_READ_SHIFT; + } } } From ede320cef66539010ea0cc9b7f9e86e54b24d544 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Mon, 17 Feb 2025 14:23:25 -0600 Subject: [PATCH 7/9] Remove unnecessary function declarations. --- shared-bindings/audiocore/RawSample.h | 4 ---- shared-bindings/audiocore/WaveFile.h | 4 ---- shared-bindings/audiodelays/Echo.h | 4 ---- shared-bindings/audiodelays/PitchShift.h | 4 ---- shared-bindings/audiofilters/Distortion.h | 4 ---- shared-bindings/audiofilters/Filter.h | 4 ---- shared-bindings/audiomixer/Mixer.h | 3 --- shared-bindings/audiomp3/MP3Decoder.h | 4 ---- shared-bindings/synthio/MidiTrack.h | 3 --- shared-bindings/synthio/Synthesizer.h | 3 --- 10 files changed, 37 deletions(-) diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h index 1f4ca7f8ec52b..a3ffd0b13c79a 100644 --- a/shared-bindings/audiocore/RawSample.h +++ b/shared-bindings/audiocore/RawSample.h @@ -16,7 +16,3 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self, void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self); bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self); -uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t *self); -uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t *self); -uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t *self); -void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t *self, uint32_t sample_rate); diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h index 7c847bbced7fb..7f2ec87c68eef 100644 --- a/shared-bindings/audiocore/WaveFile.h +++ b/shared-bindings/audiocore/WaveFile.h @@ -18,7 +18,3 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t *self); bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t *self); -uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t *self); -void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t *self, uint32_t sample_rate); -uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t *self); -uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t *self); diff --git a/shared-bindings/audiodelays/Echo.h b/shared-bindings/audiodelays/Echo.h index b276a328b3a21..23b4dee440007 100644 --- a/shared-bindings/audiodelays/Echo.h +++ b/shared-bindings/audiodelays/Echo.h @@ -18,10 +18,6 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_ void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self); bool common_hal_audiodelays_echo_deinited(audiodelays_echo_obj_t *self); -uint32_t common_hal_audiodelays_echo_get_sample_rate(audiodelays_echo_obj_t *self); -uint8_t common_hal_audiodelays_echo_get_channel_count(audiodelays_echo_obj_t *self); -uint8_t common_hal_audiodelays_echo_get_bits_per_sample(audiodelays_echo_obj_t *self); - mp_obj_t common_hal_audiodelays_echo_get_delay_ms(audiodelays_echo_obj_t *self); void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, mp_obj_t delay_ms); diff --git a/shared-bindings/audiodelays/PitchShift.h b/shared-bindings/audiodelays/PitchShift.h index 018ef150cf7e5..12d4b09f5a146 100644 --- a/shared-bindings/audiodelays/PitchShift.h +++ b/shared-bindings/audiodelays/PitchShift.h @@ -18,10 +18,6 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self); bool common_hal_audiodelays_pitch_shift_deinited(audiodelays_pitch_shift_obj_t *self); -uint32_t common_hal_audiodelays_pitch_shift_get_sample_rate(audiodelays_pitch_shift_obj_t *self); -uint8_t common_hal_audiodelays_pitch_shift_get_channel_count(audiodelays_pitch_shift_obj_t *self); -uint8_t common_hal_audiodelays_pitch_shift_get_bits_per_sample(audiodelays_pitch_shift_obj_t *self); - mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self); void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t semitones); diff --git a/shared-bindings/audiofilters/Distortion.h b/shared-bindings/audiofilters/Distortion.h index 5e4fadfd28b7c..6a11dff38fe1d 100644 --- a/shared-bindings/audiofilters/Distortion.h +++ b/shared-bindings/audiofilters/Distortion.h @@ -20,10 +20,6 @@ void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self); bool common_hal_audiofilters_distortion_deinited(audiofilters_distortion_obj_t *self); -uint32_t common_hal_audiofilters_distortion_get_sample_rate(audiofilters_distortion_obj_t *self); -uint8_t common_hal_audiofilters_distortion_get_channel_count(audiofilters_distortion_obj_t *self); -uint8_t common_hal_audiofilters_distortion_get_bits_per_sample(audiofilters_distortion_obj_t *self); - mp_obj_t common_hal_audiofilters_distortion_get_drive(audiofilters_distortion_obj_t *self); void common_hal_audiofilters_distortion_set_drive(audiofilters_distortion_obj_t *self, mp_obj_t arg); diff --git a/shared-bindings/audiofilters/Filter.h b/shared-bindings/audiofilters/Filter.h index 739b625ee6c51..07c52cfafd72b 100644 --- a/shared-bindings/audiofilters/Filter.h +++ b/shared-bindings/audiofilters/Filter.h @@ -18,10 +18,6 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self); bool common_hal_audiofilters_filter_deinited(audiofilters_filter_obj_t *self); -uint32_t common_hal_audiofilters_filter_get_sample_rate(audiofilters_filter_obj_t *self); -uint8_t common_hal_audiofilters_filter_get_channel_count(audiofilters_filter_obj_t *self); -uint8_t common_hal_audiofilters_filter_get_bits_per_sample(audiofilters_filter_obj_t *self); - mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self); void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t arg); diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h index 29577b0a61b86..e095bf14f500a 100644 --- a/shared-bindings/audiomixer/Mixer.h +++ b/shared-bindings/audiomixer/Mixer.h @@ -23,6 +23,3 @@ void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self); bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self); bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self); -uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t *self); -uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t *self); -uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t *self); diff --git a/shared-bindings/audiomp3/MP3Decoder.h b/shared-bindings/audiomp3/MP3Decoder.h index 2b6103f7b0e7b..0b485b4bca17e 100644 --- a/shared-bindings/audiomp3/MP3Decoder.h +++ b/shared-bindings/audiomp3/MP3Decoder.h @@ -19,9 +19,5 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t stream); void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self); -uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self); -void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, uint32_t sample_rate); -uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self); -uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self); float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self); uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self); diff --git a/shared-bindings/synthio/MidiTrack.h b/shared-bindings/synthio/MidiTrack.h index 215521dd8a364..72b217e9613b1 100644 --- a/shared-bindings/synthio/MidiTrack.h +++ b/shared-bindings/synthio/MidiTrack.h @@ -14,7 +14,4 @@ extern const mp_obj_type_t synthio_miditrack_type; void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self, const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj); void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self); -uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self); -uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self); -uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self); mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self); diff --git a/shared-bindings/synthio/Synthesizer.h b/shared-bindings/synthio/Synthesizer.h index 24d2f4559343b..ffadb433047fb 100644 --- a/shared-bindings/synthio/Synthesizer.h +++ b/shared-bindings/synthio/Synthesizer.h @@ -15,9 +15,6 @@ void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t envelope_obj); void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self); -uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self); -uint8_t common_hal_synthio_synthesizer_get_bits_per_sample(synthio_synthesizer_obj_t *self); -uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj_t *self); void common_hal_synthio_synthesizer_release(synthio_synthesizer_obj_t *self, mp_obj_t to_release); void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_obj_t to_press); void common_hal_synthio_synthesizer_retrigger(synthio_synthesizer_obj_t *self, mp_obj_t to_retrigger); From 9dfa9cf978ed4091716e29acd2a5136f937f8679 Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Mon, 17 Feb 2025 14:32:49 -0600 Subject: [PATCH 8/9] Call `audiosample_mark_deinit` during deinitialization of audiosample objects. --- shared-module/audiodelays/Echo.c | 2 ++ shared-module/audiodelays/PitchShift.c | 2 ++ shared-module/audiofilters/Distortion.c | 2 ++ shared-module/audiofilters/Filter.c | 2 ++ shared-module/audiomixer/Mixer.c | 2 ++ 5 files changed, 10 insertions(+) diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c index 6cb0d659d629f..4c177dc9fc835 100644 --- a/shared-module/audiodelays/Echo.c +++ b/shared-module/audiodelays/Echo.c @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: MIT #include "shared-bindings/audiodelays/Echo.h" +#include "shared-bindings/audiocore/__init__.h" #include #include "py/runtime.h" @@ -115,6 +116,7 @@ void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self) { if (common_hal_audiodelays_echo_deinited(self)) { return; } + audiosample_mark_deinit(&self->base); self->echo_buffer = NULL; self->buffer[0] = NULL; self->buffer[1] = NULL; diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index cd50e6cda94a6..0fc85ff6a6ea5 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: MIT #include "shared-bindings/audiodelays/PitchShift.h" +#include "shared-bindings/audiocore/__init__.h" #include #include "py/runtime.h" @@ -105,6 +106,7 @@ void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *se if (common_hal_audiodelays_pitch_shift_deinited(self)) { return; } + audiosample_mark_deinit(&self->base); self->window_buffer = NULL; self->overlap_buffer = NULL; self->buffer[0] = NULL; diff --git a/shared-module/audiofilters/Distortion.c b/shared-module/audiofilters/Distortion.c index 1e44f08e83346..b5c6752e0ce15 100644 --- a/shared-module/audiofilters/Distortion.c +++ b/shared-module/audiofilters/Distortion.c @@ -10,6 +10,7 @@ #include #include "shared-bindings/audiofilters/Distortion.h" #include "shared-module/audiofilters/Distortion.h" +#include "shared-bindings/audiocore/__init__.h" /** * Based on Godot's AudioEffectDistortion @@ -81,6 +82,7 @@ bool common_hal_audiofilters_distortion_deinited(audiofilters_distortion_obj_t * } void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self) { + audiosample_mark_deinit(&self->base); self->buffer[0] = NULL; self->buffer[1] = NULL; } diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index 66b98b740bd5b..66b6dd71cb2ce 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: MIT #include "shared-bindings/audiofilters/Filter.h" +#include "shared-bindings/audiocore/__init__.h" #include "shared-module/synthio/BlockBiquad.h" #include @@ -67,6 +68,7 @@ void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self) { if (common_hal_audiofilters_filter_deinited(self)) { return; } + audiosample_mark_deinit(&self->base); self->buffer[0] = NULL; self->buffer[1] = NULL; self->filter = mp_const_none; diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 60939f1a30aae..4becbba687f4a 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -11,6 +11,7 @@ #include "py/runtime.h" #include "shared-module/audiocore/__init__.h" +#include "shared-bindings/audiocore/__init__.h" #if defined(__arm__) && __arm__ #include "cmsis_compiler.h" @@ -47,6 +48,7 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self, } void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self) { + audiosample_mark_deinit(&self->base); self->first_buffer = NULL; self->second_buffer = NULL; } From 94a234fbc110a5cedc887244e7fb7aea4141bc8c Mon Sep 17 00:00:00 2001 From: dcooperdalrymple Date: Tue, 18 Feb 2025 20:38:44 -0600 Subject: [PATCH 9/9] Remove unnecessary deinited functions for audiosample objects. --- shared-bindings/audiocore/RawSample.h | 1 - shared-bindings/audiocore/WaveFile.h | 1 - shared-bindings/audiodelays/Echo.h | 1 - shared-bindings/audiodelays/PitchShift.h | 1 - shared-bindings/audiofilters/Distortion.h | 1 - shared-bindings/audiofilters/Filter.h | 1 - shared-bindings/audiomixer/Mixer.h | 1 - shared-module/audiodelays/Echo.c | 10 ---------- shared-module/audiodelays/PitchShift.c | 10 ---------- shared-module/audiofilters/Distortion.c | 7 ------- shared-module/audiofilters/Filter.c | 10 ---------- shared-module/audiomixer/Mixer.c | 4 ---- 12 files changed, 48 deletions(-) diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h index a3ffd0b13c79a..a5b9b06e79700 100644 --- a/shared-bindings/audiocore/RawSample.h +++ b/shared-bindings/audiocore/RawSample.h @@ -15,4 +15,3 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self, uint8_t channel_count, uint32_t sample_rate, bool single_buffer); void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self); -bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self); diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h index 7f2ec87c68eef..5249959a1cc50 100644 --- a/shared-bindings/audiocore/WaveFile.h +++ b/shared-bindings/audiocore/WaveFile.h @@ -17,4 +17,3 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, 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-bindings/audiodelays/Echo.h b/shared-bindings/audiodelays/Echo.h index 23b4dee440007..83d454ed05c57 100644 --- a/shared-bindings/audiodelays/Echo.h +++ b/shared-bindings/audiodelays/Echo.h @@ -16,7 +16,6 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_ uint8_t channel_count, uint32_t sample_rate, bool freq_shift); void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self); -bool common_hal_audiodelays_echo_deinited(audiodelays_echo_obj_t *self); mp_obj_t common_hal_audiodelays_echo_get_delay_ms(audiodelays_echo_obj_t *self); void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, mp_obj_t delay_ms); diff --git a/shared-bindings/audiodelays/PitchShift.h b/shared-bindings/audiodelays/PitchShift.h index 12d4b09f5a146..78c78b5ea828e 100644 --- a/shared-bindings/audiodelays/PitchShift.h +++ b/shared-bindings/audiodelays/PitchShift.h @@ -16,7 +16,6 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t uint8_t channel_count, uint32_t sample_rate); void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self); -bool common_hal_audiodelays_pitch_shift_deinited(audiodelays_pitch_shift_obj_t *self); mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self); void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t semitones); diff --git a/shared-bindings/audiofilters/Distortion.h b/shared-bindings/audiofilters/Distortion.h index 6a11dff38fe1d..ded32eada303a 100644 --- a/shared-bindings/audiofilters/Distortion.h +++ b/shared-bindings/audiofilters/Distortion.h @@ -18,7 +18,6 @@ void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t uint8_t channel_count, uint32_t sample_rate); void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self); -bool common_hal_audiofilters_distortion_deinited(audiofilters_distortion_obj_t *self); mp_obj_t common_hal_audiofilters_distortion_get_drive(audiofilters_distortion_obj_t *self); void common_hal_audiofilters_distortion_set_drive(audiofilters_distortion_obj_t *self, mp_obj_t arg); diff --git a/shared-bindings/audiofilters/Filter.h b/shared-bindings/audiofilters/Filter.h index 07c52cfafd72b..e8dac00ba9ffd 100644 --- a/shared-bindings/audiofilters/Filter.h +++ b/shared-bindings/audiofilters/Filter.h @@ -16,7 +16,6 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, uint8_t channel_count, uint32_t sample_rate); void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self); -bool common_hal_audiofilters_filter_deinited(audiofilters_filter_obj_t *self); mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self); void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t arg); diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h index e095bf14f500a..3e6e5890f44e0 100644 --- a/shared-bindings/audiomixer/Mixer.h +++ b/shared-bindings/audiomixer/Mixer.h @@ -20,6 +20,5 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self, uint32_t sample_rate); void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self); -bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self); bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self); diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c index 4c177dc9fc835..968c3bbddb693 100644 --- a/shared-module/audiodelays/Echo.c +++ b/shared-module/audiodelays/Echo.c @@ -105,17 +105,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_ self->echo_buffer_left_pos = self->echo_buffer_right_pos = 0; } -bool common_hal_audiodelays_echo_deinited(audiodelays_echo_obj_t *self) { - if (self->echo_buffer == NULL) { - return true; - } - return false; -} - void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self) { - if (common_hal_audiodelays_echo_deinited(self)) { - return; - } audiosample_mark_deinit(&self->base); self->echo_buffer = NULL; self->buffer[0] = NULL; diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c index 0fc85ff6a6ea5..743ba403d7961 100644 --- a/shared-module/audiodelays/PitchShift.c +++ b/shared-module/audiodelays/PitchShift.c @@ -95,17 +95,7 @@ void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t recalculate_rate(self, f_semitones); } -bool common_hal_audiodelays_pitch_shift_deinited(audiodelays_pitch_shift_obj_t *self) { - if (self->window_buffer == NULL) { - return true; - } - return false; -} - void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self) { - if (common_hal_audiodelays_pitch_shift_deinited(self)) { - return; - } audiosample_mark_deinit(&self->base); self->window_buffer = NULL; self->overlap_buffer = NULL; diff --git a/shared-module/audiofilters/Distortion.c b/shared-module/audiofilters/Distortion.c index b5c6752e0ce15..b1f22c4854528 100644 --- a/shared-module/audiofilters/Distortion.c +++ b/shared-module/audiofilters/Distortion.c @@ -74,13 +74,6 @@ void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t self->soft_clip = soft_clip; } -bool common_hal_audiofilters_distortion_deinited(audiofilters_distortion_obj_t *self) { - if (self->buffer[0] == NULL) { - return true; - } - return false; -} - void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self) { audiosample_mark_deinit(&self->base); self->buffer[0] = NULL; diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index 66b6dd71cb2ce..10876c44f7cbc 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -57,17 +57,7 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); } -bool common_hal_audiofilters_filter_deinited(audiofilters_filter_obj_t *self) { - if (self->buffer[0] == NULL) { - return true; - } - return false; -} - void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self) { - if (common_hal_audiofilters_filter_deinited(self)) { - return; - } audiosample_mark_deinit(&self->base); self->buffer[0] = NULL; self->buffer[1] = NULL; diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 4becbba687f4a..775ab41d42f73 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -53,10 +53,6 @@ void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self) { self->second_buffer = NULL; } -bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self) { - return self->first_buffer == NULL; -} - bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self) { for (uint8_t v = 0; v < self->voice_count; v++) { if (common_hal_audiomixer_mixervoice_get_playing(MP_OBJ_TO_PTR(self->voice[v]))) {