Moving to audiofreeverb and renaming to Freeverb

This commit is contained in:
gamblor21 2025-04-11 17:15:50 -05:00
parent 6e7d2b5ddf
commit 86eca38566
12 changed files with 212 additions and 155 deletions

View file

@ -137,6 +137,9 @@ endif
ifeq ($(CIRCUITPY_AUDIOFILTERS),1)
SRC_PATTERNS += audiofilters/%
endif
ifeq ($(CIRCUITPY_AUDIOFREEVERB),1)
SRC_PATTERNS += audiofreeverb/%
endif
ifeq ($(CIRCUITPY_AUDIOMIXER),1)
SRC_PATTERNS += audiomixer/%
endif
@ -633,11 +636,12 @@ SRC_SHARED_MODULE_ALL = \
audiocore/__init__.c \
audiodelays/Echo.c \
audiodelays/PitchShift.c \
audiodelays/Reverb.c \
audiodelays/__init__.c \
audiofilters/Distortion.c \
audiofilters/Filter.c \
audiofilters/__init__.c \
audiofreeverb/__init__.c \
audiofreeverb/Freeverb.c \
audioio/__init__.c \
audiomixer/Mixer.c \
audiomixer/MixerVoice.c \

View file

@ -146,6 +146,8 @@ CIRCUITPY_AUDIODELAYS ?= $(CIRCUITPY_AUDIOEFFECTS)
CFLAGS += -DCIRCUITPY_AUDIODELAYS=$(CIRCUITPY_AUDIODELAYS)
CIRCUITPY_AUDIOFILTERS ?= $(CIRCUITPY_AUDIOEFFECTS)
CFLAGS += -DCIRCUITPY_AUDIOFILTERS=$(CIRCUITPY_AUDIOFILTERS)
CIRCUITPY_AUDIOFREEVERB ?= $(CIRCUITPY_AUDIOEFFECTS)
CFLAGS += -DCIRCUITPY_AUDIOFREEVERB=$(CIRCUITPY_AUDIOFREEVERB)
CIRCUITPY_AURORA_EPAPER ?= 0
CFLAGS += -DCIRCUITPY_AURORA_EPAPER=$(CIRCUITPY_AURORA_EPAPER)

View file

@ -1,36 +0,0 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
//
// SPDX-License-Identifier: MIT
#pragma once
#include "shared-module/audiodelays/Reverb.h"
extern const mp_obj_type_t audiodelays_reverb_type;
void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self,
mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed,
uint8_t channel_count, uint32_t sample_rate);
void common_hal_audiodelays_reverb_deinit(audiodelays_reverb_obj_t *self);
bool common_hal_audiodelays_reverb_deinited(audiodelays_reverb_obj_t *self);
uint32_t common_hal_audiodelays_reverb_get_sample_rate(audiodelays_reverb_obj_t *self);
uint8_t common_hal_audiodelays_reverb_get_channel_count(audiodelays_reverb_obj_t *self);
uint8_t common_hal_audiodelays_reverb_get_bits_per_sample(audiodelays_reverb_obj_t *self);
mp_obj_t common_hal_audiodelays_reverb_get_roomsize(audiodelays_reverb_obj_t *self);
void common_hal_audiodelays_reverb_set_roomsize(audiodelays_reverb_obj_t *self, mp_obj_t feedback);
mp_obj_t common_hal_audiodelays_reverb_get_damp(audiodelays_reverb_obj_t *self);
void common_hal_audiodelays_reverb_set_damp(audiodelays_reverb_obj_t *self, mp_obj_t damp);
mp_obj_t common_hal_audiodelays_reverb_get_mix(audiodelays_reverb_obj_t *self);
void common_hal_audiodelays_reverb_set_mix(audiodelays_reverb_obj_t *self, mp_obj_t mix);
bool common_hal_audiodelays_reverb_get_playing(audiodelays_reverb_obj_t *self);
void common_hal_audiodelays_reverb_play(audiodelays_reverb_obj_t *self, mp_obj_t sample, bool loop);
void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self);

View file

@ -12,7 +12,6 @@
#include "shared-bindings/audiodelays/__init__.h"
#include "shared-bindings/audiodelays/Echo.h"
#include "shared-bindings/audiodelays/PitchShift.h"
#include "shared-bindings/audiodelays/Reverb.h"
//| """Support for audio delay effects
@ -25,7 +24,6 @@ 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) },
{ MP_ROM_QSTR(MP_QSTR_Reverb), MP_ROM_PTR(&audiodelays_reverb_type) },
};
static MP_DEFINE_CONST_DICT(audiodelays_module_globals, audiodelays_module_globals_table);

View file

@ -6,9 +6,9 @@
#include <stdint.h>
#include "shared-bindings/audiodelays/Reverb.h"
#include "shared-bindings/audiofreeverb/Freeverb.h"
#include "shared-bindings/audiocore/__init__.h"
#include "shared-module/audiodelays/Reverb.h"
#include "shared-module/audiofreeverb/Freeverb.h"
#include "shared/runtime/context_manager_helpers.h"
#include "py/binary.h"
@ -17,8 +17,8 @@
#include "shared-bindings/util.h"
#include "shared-module/synthio/block.h"
//| class Reverb:
//| """An Reverb effect"""
//| class Freeverb:
//| """An Freeverb effect"""
//|
//| def __init__(
//| self,
@ -44,20 +44,20 @@
//| :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. Reverb requires 16 bits.
//| :param bool samples_signed: Effect is signed (True) or unsigned (False). Reverb requires signed (True).
//| :param int bits_per_sample: The bits per sample of the effect. Freeverb requires 16 bits.
//| :param bool samples_signed: Effect is signed (True) or unsigned (False). Freeverb requires signed (True).
//|
//| Playing adding an reverb to a synth::
//| Playing adding reverb to a synth::
//|
//| import time
//| import board
//| import audiobusio
//| import synthio
//| import audiodelays
//| import audiofreeverb
//|
//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22)
//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100)
//| reverb = audiodelays.Reverb(roomsize=0.7, damp=0.3, buffer_size=1024, channel_count=1, sample_rate=44100, mix=0.7)
//| reverb = audiofreeverb.Freeverb(roomsize=0.7, damp=0.3, buffer_size=1024, channel_count=1, sample_rate=44100, mix=0.7)
//| reverb.play(synth)
//| audio.play(reverb)
//|
@ -69,7 +69,7 @@
//| time.sleep(5)"""
//| ...
//|
static mp_obj_t audiodelays_reverb_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
static mp_obj_t audiofreeverb_freeverb_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_roomsize, ARG_damp, ARG_mix, 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_roomsize, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
@ -95,28 +95,28 @@ static mp_obj_t audiodelays_reverb_make_new(const mp_obj_type_t *type, size_t n_
mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 16"));
}
audiodelays_reverb_obj_t *self = mp_obj_malloc(audiodelays_reverb_obj_t, &audiodelays_reverb_type);
common_hal_audiodelays_reverb_construct(self, args[ARG_roomsize].u_obj, args[ARG_damp].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
audiofreeverb_freeverb_obj_t *self = mp_obj_malloc(audiofreeverb_freeverb_obj_t, &audiofreeverb_freeverb_type);
common_hal_audiofreeverb_freeverb_construct(self, args[ARG_roomsize].u_obj, args[ARG_damp].u_obj, args[ARG_mix].u_obj, 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 Reverb."""
//| """Deinitialises the Freeverb."""
//| ...
//|
static mp_obj_t audiodelays_reverb_deinit(mp_obj_t self_in) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiodelays_reverb_deinit(self);
static mp_obj_t audiofreeverb_freeverb_deinit(mp_obj_t self_in) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiofreeverb_freeverb_deinit(self);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_deinit_obj, audiodelays_reverb_deinit);
static MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_deinit_obj, audiofreeverb_freeverb_deinit);
static void check_for_deinit(audiodelays_reverb_obj_t *self) {
static void check_for_deinit(audiofreeverb_freeverb_obj_t *self) {
audiosample_check_for_deinit(&self->base);
}
//| def __enter__(self) -> Reverb:
//| def __enter__(self) -> Freeverb:
//| """No-op used by Context Managers."""
//| ...
//|
@ -131,70 +131,70 @@ static void check_for_deinit(audiodelays_reverb_obj_t *self) {
//| roomsize: synthio.BlockInput
//| """Apparent size of the room 0.0-1.0"""
static mp_obj_t audiodelays_reverb_obj_get_roomsize(mp_obj_t self_in) {
return common_hal_audiodelays_reverb_get_roomsize(self_in);
static mp_obj_t audiofreeverb_freeverb_obj_get_roomsize(mp_obj_t self_in) {
return common_hal_audiofreeverb_freeverb_get_roomsize(self_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_roomsize_obj, audiodelays_reverb_obj_get_roomsize);
MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_roomsize_obj, audiofreeverb_freeverb_obj_get_roomsize);
static mp_obj_t audiodelays_reverb_obj_set_roomsize(mp_obj_t self_in, mp_obj_t roomsize) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiodelays_reverb_set_roomsize(self, roomsize);
static mp_obj_t audiofreeverb_freeverb_obj_set_roomsize(mp_obj_t self_in, mp_obj_t roomsize) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiofreeverb_freeverb_set_roomsize(self, roomsize);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_roomsize_obj, audiodelays_reverb_obj_set_roomsize);
MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_roomsize_obj, audiofreeverb_freeverb_obj_set_roomsize);
MP_PROPERTY_GETSET(audiodelays_reverb_roomsize_obj,
(mp_obj_t)&audiodelays_reverb_get_roomsize_obj,
(mp_obj_t)&audiodelays_reverb_set_roomsize_obj);
MP_PROPERTY_GETSET(audiofreeverb_freeverb_roomsize_obj,
(mp_obj_t)&audiofreeverb_freeverb_get_roomsize_obj,
(mp_obj_t)&audiofreeverb_freeverb_set_roomsize_obj);
//| damp: synthio.BlockInput
//| """How much the high frequencies are dampened in the area. 0.0-1.0"""
static mp_obj_t audiodelays_reverb_obj_get_damp(mp_obj_t self_in) {
return common_hal_audiodelays_reverb_get_damp(self_in);
static mp_obj_t audiofreeverb_freeverb_obj_get_damp(mp_obj_t self_in) {
return common_hal_audiofreeverb_freeverb_get_damp(self_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_damp_obj, audiodelays_reverb_obj_get_damp);
MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_damp_obj, audiofreeverb_freeverb_obj_get_damp);
static mp_obj_t audiodelays_reverb_obj_set_damp(mp_obj_t self_in, mp_obj_t damp) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiodelays_reverb_set_damp(self, damp);
static mp_obj_t audiofreeverb_freeverb_obj_set_damp(mp_obj_t self_in, mp_obj_t damp) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiofreeverb_freeverb_set_damp(self, damp);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_damp_obj, audiodelays_reverb_obj_set_damp);
MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_damp_obj, audiofreeverb_freeverb_obj_set_damp);
MP_PROPERTY_GETSET(audiodelays_reverb_damp_obj,
(mp_obj_t)&audiodelays_reverb_get_damp_obj,
(mp_obj_t)&audiodelays_reverb_set_damp_obj);
MP_PROPERTY_GETSET(audiofreeverb_freeverb_damp_obj,
(mp_obj_t)&audiofreeverb_freeverb_get_damp_obj,
(mp_obj_t)&audiofreeverb_freeverb_set_damp_obj);
//| mix: synthio.BlockInput
//| """The rate the reverb mix between 0 and 1 where 0 is only sample and 1 is all effect."""
static mp_obj_t audiodelays_reverb_obj_get_mix(mp_obj_t self_in) {
return common_hal_audiodelays_reverb_get_mix(self_in);
static mp_obj_t audiofreeverb_freeverb_obj_get_mix(mp_obj_t self_in) {
return common_hal_audiofreeverb_freeverb_get_mix(self_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_mix_obj, audiodelays_reverb_obj_get_mix);
MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_mix_obj, audiofreeverb_freeverb_obj_get_mix);
static mp_obj_t audiodelays_reverb_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiodelays_reverb_set_mix(self, mix_in);
static mp_obj_t audiofreeverb_freeverb_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiofreeverb_freeverb_set_mix(self, mix_in);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_mix_obj, audiodelays_reverb_obj_set_mix);
MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_mix_obj, audiofreeverb_freeverb_obj_set_mix);
MP_PROPERTY_GETSET(audiodelays_reverb_mix_obj,
(mp_obj_t)&audiodelays_reverb_get_mix_obj,
(mp_obj_t)&audiodelays_reverb_set_mix_obj);
MP_PROPERTY_GETSET(audiofreeverb_freeverb_mix_obj,
(mp_obj_t)&audiofreeverb_freeverb_get_mix_obj,
(mp_obj_t)&audiofreeverb_freeverb_set_mix_obj);
//| playing: bool
//| """True when the effect is playing a sample. (read-only)"""
//|
static mp_obj_t audiodelays_reverb_obj_get_playing(mp_obj_t self_in) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
static mp_obj_t audiofreeverb_freeverb_obj_get_playing(mp_obj_t self_in) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self);
return mp_obj_new_bool(common_hal_audiodelays_reverb_get_playing(self));
return mp_obj_new_bool(common_hal_audiofreeverb_freeverb_get_playing(self));
}
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_playing_obj, audiodelays_reverb_obj_get_playing);
MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_playing_obj, audiofreeverb_freeverb_obj_get_playing);
MP_PROPERTY_GETTER(audiodelays_reverb_playing_obj,
(mp_obj_t)&audiodelays_reverb_get_playing_obj);
MP_PROPERTY_GETTER(audiofreeverb_freeverb_playing_obj,
(mp_obj_t)&audiofreeverb_freeverb_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.
@ -203,66 +203,66 @@ MP_PROPERTY_GETTER(audiodelays_reverb_playing_obj,
//| The sample must match the encoding settings given in the constructor."""
//| ...
//|
static mp_obj_t audiodelays_reverb_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static mp_obj_t audiofreeverb_freeverb_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_reverb_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
audiofreeverb_freeverb_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_reverb_play(self, sample, args[ARG_loop].u_bool);
common_hal_audiofreeverb_freeverb_play(self, sample, args[ARG_loop].u_bool);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_reverb_play_obj, 1, audiodelays_reverb_obj_play);
MP_DEFINE_CONST_FUN_OBJ_KW(audiofreeverb_freeverb_play_obj, 1, audiofreeverb_freeverb_obj_play);
//| def stop(self) -> None:
//| """Stops playback of the sample. The reverb continues playing."""
//| ...
//|
//|
static mp_obj_t audiodelays_reverb_obj_stop(mp_obj_t self_in) {
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
static mp_obj_t audiofreeverb_freeverb_obj_stop(mp_obj_t self_in) {
audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
common_hal_audiodelays_reverb_stop(self);
common_hal_audiofreeverb_freeverb_stop(self);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_stop_obj, audiodelays_reverb_obj_stop);
MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_stop_obj, audiofreeverb_freeverb_obj_stop);
static const mp_rom_map_elem_t audiodelays_reverb_locals_dict_table[] = {
static const mp_rom_map_elem_t audiofreeverb_freeverb_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_reverb_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiofreeverb_freeverb_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) },
{ MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_reverb_play_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_reverb_stop_obj) },
{ MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiofreeverb_freeverb_play_obj) },
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiofreeverb_freeverb_stop_obj) },
// Properties
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_reverb_playing_obj) },
{ MP_ROM_QSTR(MP_QSTR_roomsize), MP_ROM_PTR(&audiodelays_reverb_roomsize_obj) },
{ MP_ROM_QSTR(MP_QSTR_damp), MP_ROM_PTR(&audiodelays_reverb_damp_obj) },
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_reverb_mix_obj) },
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofreeverb_freeverb_playing_obj) },
{ MP_ROM_QSTR(MP_QSTR_roomsize), MP_ROM_PTR(&audiofreeverb_freeverb_roomsize_obj) },
{ MP_ROM_QSTR(MP_QSTR_damp), MP_ROM_PTR(&audiofreeverb_freeverb_damp_obj) },
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofreeverb_freeverb_mix_obj) },
AUDIOSAMPLE_FIELDS,
};
static MP_DEFINE_CONST_DICT(audiodelays_reverb_locals_dict, audiodelays_reverb_locals_dict_table);
static MP_DEFINE_CONST_DICT(audiofreeverb_freeverb_locals_dict, audiofreeverb_freeverb_locals_dict_table);
static const audiosample_p_t audiodelays_reverb_proto = {
static const audiosample_p_t audiofreeverb_freeverb_proto = {
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
.reset_buffer = (audiosample_reset_buffer_fun)audiodelays_reverb_reset_buffer,
.get_buffer = (audiosample_get_buffer_fun)audiodelays_reverb_get_buffer,
.reset_buffer = (audiosample_reset_buffer_fun)audiofreeverb_freeverb_reset_buffer,
.get_buffer = (audiosample_get_buffer_fun)audiofreeverb_freeverb_get_buffer,
};
MP_DEFINE_CONST_OBJ_TYPE(
audiodelays_reverb_type,
MP_QSTR_Reverb,
audiofreeverb_freeverb_type,
MP_QSTR_freeverb,
MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS,
make_new, audiodelays_reverb_make_new,
locals_dict, &audiodelays_reverb_locals_dict,
protocol, &audiodelays_reverb_proto
make_new, audiofreeverb_freeverb_make_new,
locals_dict, &audiofreeverb_freeverb_locals_dict,
protocol, &audiofreeverb_freeverb_proto
);

View file

@ -0,0 +1,36 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
//
// SPDX-License-Identifier: MIT
#pragma once
#include "shared-module/audiofreeverb/Freeverb.h"
extern const mp_obj_type_t audiofreeverb_freeverb_type;
void common_hal_audiofreeverb_freeverb_construct(audiofreeverb_freeverb_obj_t *self,
mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed,
uint8_t channel_count, uint32_t sample_rate);
void common_hal_audiofreeverb_freeverb_deinit(audiofreeverb_freeverb_obj_t *self);
bool common_hal_audiofreeverb_freeverb_deinited(audiofreeverb_freeverb_obj_t *self);
uint32_t common_hal_audiofreeverb_freeverb_get_sample_rate(audiofreeverb_freeverb_obj_t *self);
uint8_t common_hal_audiofreeverb_freeverb_get_channel_count(audiofreeverb_freeverb_obj_t *self);
uint8_t common_hal_audiofreeverb_freeverb_get_bits_per_sample(audiofreeverb_freeverb_obj_t *self);
mp_obj_t common_hal_audiofreeverb_freeverb_get_roomsize(audiofreeverb_freeverb_obj_t *self);
void common_hal_audiofreeverb_freeverb_set_roomsize(audiofreeverb_freeverb_obj_t *self, mp_obj_t feedback);
mp_obj_t common_hal_audiofreeverb_freeverb_get_damp(audiofreeverb_freeverb_obj_t *self);
void common_hal_audiofreeverb_freeverb_set_damp(audiofreeverb_freeverb_obj_t *self, mp_obj_t damp);
mp_obj_t common_hal_audiofreeverb_freeverb_get_mix(audiofreeverb_freeverb_obj_t *self);
void common_hal_audiofreeverb_freeverb_set_mix(audiofreeverb_freeverb_obj_t *self, mp_obj_t mix);
bool common_hal_audiofreeverb_freeverb_get_playing(audiofreeverb_freeverb_obj_t *self);
void common_hal_audiofreeverb_freeverb_play(audiofreeverb_freeverb_obj_t *self, mp_obj_t sample, bool loop);
void common_hal_audiofreeverb_freeverb_stop(audiofreeverb_freeverb_obj_t *self);

View file

@ -0,0 +1,34 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus
//
// SPDX-License-Identifier: MIT
#include <stdint.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "shared-bindings/audiofreeverb/__init__.h"
#include "shared-bindings/audiofreeverb/Freeverb.h"
//| """Support for audio freeverb effect
//|
//| The `audiofreeverb` module contains classes to provide access to audio freeverb effects.
//|
//| """
static const mp_rom_map_elem_t audiofreeverb_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiofreeverb) },
{ MP_ROM_QSTR(MP_QSTR_Freeverb), MP_ROM_PTR(&audiofreeverb_freeverb_type) },
};
static MP_DEFINE_CONST_DICT(audiofreeverb_module_globals, audiofreeverb_module_globals_table);
const mp_obj_module_t audiofreeverb_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&audiofreeverb_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_audiofreeverb, audiofreeverb_module);

View file

@ -0,0 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
//
// SPDX-License-Identifier: MIT
#pragma once

View file

@ -7,13 +7,13 @@
// Based on FreeVerb - https://github.com/sinshu/freeverb/tree/main
// Fixed point ideas from - Paul Stoffregen in the Teensy audio library https://github.com/PaulStoffregen/Audio/blob/master/effect_freeverb.cpp
//
#include "shared-bindings/audiodelays/Reverb.h"
#include "shared-bindings/audiofreeverb/Freeverb.h"
#include <stdint.h>
#include "py/runtime.h"
#include <math.h>
void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
void common_hal_audiofreeverb_freeverb_construct(audiofreeverb_freeverb_obj_t *self, mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
uint32_t buffer_size, uint8_t bits_per_sample,
bool samples_signed, uint8_t channel_count, uint32_t sample_rate) {
@ -35,14 +35,14 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_
self->buffer[0] = m_malloc(self->buffer_len);
if (self->buffer[0] == NULL) {
common_hal_audiodelays_reverb_deinit(self);
common_hal_audiofreeverb_freeverb_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_reverb_deinit(self);
common_hal_audiofreeverb_freeverb_deinit(self);
m_malloc_fail(self->buffer_len);
}
memset(self->buffer[1], 0, self->buffer_len);
@ -61,19 +61,19 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_
roomsize = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
}
synthio_block_assign_slot(roomsize, &self->roomsize, MP_QSTR_roomsize);
common_hal_audiodelays_reverb_set_roomsize(self, roomsize);
common_hal_audiofreeverb_freeverb_set_roomsize(self, roomsize);
if (damp == MP_OBJ_NULL) {
damp = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
}
synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp);
common_hal_audiodelays_reverb_set_damp(self, damp);
common_hal_audiofreeverb_freeverb_set_damp(self, damp);
if (mix == MP_OBJ_NULL) {
mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
}
synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix);
common_hal_audiodelays_reverb_set_mix(self, mix);
common_hal_audiofreeverb_freeverb_set_mix(self, mix);
// Set up the comb filters
// These values come from FreeVerb and are selected for the best reverb sound
@ -88,7 +88,7 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_
for (uint32_t i = 0; i < 8 * channel_count; i++) {
self->combbuffers[i] = m_malloc(self->combbuffersizes[i] * sizeof(uint16_t));
if (self->combbuffers[i] == NULL) {
common_hal_audiodelays_reverb_deinit(self);
common_hal_audiofreeverb_freeverb_deinit(self);
m_malloc_fail(self->combbuffersizes[i]);
}
memset(self->combbuffers[i], 0, self->combbuffersizes[i]);
@ -106,7 +106,7 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_
for (uint32_t i = 0; i < 4 * channel_count; i++) {
self->allpassbuffers[i] = m_malloc(self->allpassbuffersizes[i] * sizeof(uint16_t));
if (self->allpassbuffers[i] == NULL) {
common_hal_audiodelays_reverb_deinit(self);
common_hal_audiofreeverb_freeverb_deinit(self);
m_malloc_fail(self->allpassbuffersizes[i]);
}
memset(self->allpassbuffers[i], 0, self->allpassbuffersizes[i]);
@ -115,30 +115,30 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_
}
}
bool common_hal_audiodelays_reverb_deinited(audiodelays_reverb_obj_t *self) {
bool common_hal_audiofreeverb_freeverb_deinited(audiofreeverb_freeverb_obj_t *self) {
if (self->buffer[0] == NULL) {
return true;
}
return false;
}
void common_hal_audiodelays_reverb_deinit(audiodelays_reverb_obj_t *self) {
if (common_hal_audiodelays_reverb_deinited(self)) {
void common_hal_audiofreeverb_freeverb_deinit(audiofreeverb_freeverb_obj_t *self) {
if (common_hal_audiofreeverb_freeverb_deinited(self)) {
return;
}
self->buffer[0] = NULL;
self->buffer[1] = NULL;
}
mp_obj_t common_hal_audiodelays_reverb_get_roomsize(audiodelays_reverb_obj_t *self) {
mp_obj_t common_hal_audiofreeverb_freeverb_get_roomsize(audiofreeverb_freeverb_obj_t *self) {
return self->roomsize.obj;
}
void common_hal_audiodelays_reverb_set_roomsize(audiodelays_reverb_obj_t *self, mp_obj_t roomsize_obj) {
void common_hal_audiofreeverb_freeverb_set_roomsize(audiofreeverb_freeverb_obj_t *self, mp_obj_t roomsize_obj) {
synthio_block_assign_slot(roomsize_obj, &self->roomsize, MP_QSTR_roomsize);
}
int16_t audiodelays_reverb_get_roomsize_fixedpoint(mp_float_t n) {
int16_t audiofreeverb_freeverb_get_roomsize_fixedpoint(mp_float_t n) {
if (n > (mp_float_t)MICROPY_FLOAT_CONST(1.0)) {
n = MICROPY_FLOAT_CONST(1.0);
} else if (n < (mp_float_t)MICROPY_FLOAT_CONST(0.0)) {
@ -148,15 +148,15 @@ int16_t audiodelays_reverb_get_roomsize_fixedpoint(mp_float_t n) {
return (int16_t)(n * (mp_float_t)MICROPY_FLOAT_CONST(9175.04)) + 22937; // 9175.04 = 0.28f in fixed point 22937 = 0.7f
}
mp_obj_t common_hal_audiodelays_reverb_get_damp(audiodelays_reverb_obj_t *self) {
mp_obj_t common_hal_audiofreeverb_freeverb_get_damp(audiofreeverb_freeverb_obj_t *self) {
return self->damp.obj;
}
void common_hal_audiodelays_reverb_set_damp(audiodelays_reverb_obj_t *self, mp_obj_t damp) {
void common_hal_audiofreeverb_freeverb_set_damp(audiofreeverb_freeverb_obj_t *self, mp_obj_t damp) {
synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp);
}
void audiodelays_reverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2) {
void audiofreeverb_freeverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2) {
if (n > (mp_float_t)MICROPY_FLOAT_CONST(1.0)) {
n = MICROPY_FLOAT_CONST(1.0);
} else if (n < (mp_float_t)MICROPY_FLOAT_CONST(0.0)) {
@ -167,21 +167,21 @@ void audiodelays_reverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_
*damp2 = (int16_t)(32768 - *damp1); // inverse of x1 damp2 = 1.0 - damp1
}
mp_obj_t common_hal_audiodelays_reverb_get_mix(audiodelays_reverb_obj_t *self) {
mp_obj_t common_hal_audiofreeverb_freeverb_get_mix(audiofreeverb_freeverb_obj_t *self) {
return self->mix.obj;
}
void common_hal_audiodelays_reverb_set_mix(audiodelays_reverb_obj_t *self, mp_obj_t mix) {
void common_hal_audiofreeverb_freeverb_set_mix(audiofreeverb_freeverb_obj_t *self, mp_obj_t mix) {
synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix);
}
void audiodelays_reverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect) {
void audiofreeverb_freeverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect) {
mix = mix * (mp_float_t)MICROPY_FLOAT_CONST(2.0);
*mix_sample = (int16_t)MIN((mp_float_t)MICROPY_FLOAT_CONST(2.0) - mix, (mp_float_t)MICROPY_FLOAT_CONST(1.0)) * 32767;
*mix_effect = (int16_t)MIN(mix, (mp_float_t)MICROPY_FLOAT_CONST(1.0)) * 32767;
}
void audiodelays_reverb_reset_buffer(audiodelays_reverb_obj_t *self,
void audiofreeverb_freeverb_reset_buffer(audiofreeverb_freeverb_obj_t *self,
bool single_channel_output,
uint8_t channel) {
@ -189,11 +189,11 @@ void audiodelays_reverb_reset_buffer(audiodelays_reverb_obj_t *self,
memset(self->buffer[1], 0, self->buffer_len);
}
bool common_hal_audiodelays_reverb_get_playing(audiodelays_reverb_obj_t *self) {
bool common_hal_audiofreeverb_freeverb_get_playing(audiofreeverb_freeverb_obj_t *self) {
return self->sample != NULL;
}
void common_hal_audiodelays_reverb_play(audiodelays_reverb_obj_t *self, mp_obj_t sample, bool loop) {
void common_hal_audiofreeverb_freeverb_play(audiofreeverb_freeverb_obj_t *self, mp_obj_t sample, bool loop) {
audiosample_must_match(&self->base, sample);
self->sample = sample;
@ -210,7 +210,7 @@ void common_hal_audiodelays_reverb_play(audiodelays_reverb_obj_t *self, mp_obj_t
return;
}
void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self) {
void common_hal_audiofreeverb_freeverb_stop(audiofreeverb_freeverb_obj_t *self) {
// When the sample is set to stop playing do any cleanup here
// For reverb we clear the sample but the reverb continues until the object reading our effect stops
self->sample = NULL;
@ -238,7 +238,7 @@ static int16_t sat16(int32_t n, int rshift) {
return n;
}
audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj_t *self, bool single_channel_output, uint8_t channel,
audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_freeverb_obj_t *self, bool single_channel_output, uint8_t channel,
uint8_t **buffer, uint32_t *buffer_length) {
// Switch our buffers to the other buffer
@ -280,14 +280,14 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
mp_float_t damp = synthio_block_slot_get_limited(&self->damp, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
int16_t damp1, damp2;
audiodelays_reverb_get_damp_fixedpoint(damp, &damp1, &damp2);
audiofreeverb_freeverb_get_damp_fixedpoint(damp, &damp1, &damp2);
mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
int16_t mix_sample, mix_effect;
audiodelays_reverb_get_mix_fixedpoint(mix, &mix_sample, &mix_effect);
audiofreeverb_freeverb_get_mix_fixedpoint(mix, &mix_sample, &mix_effect);
mp_float_t roomsize = synthio_block_slot_get_limited(&self->roomsize, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
int16_t feedback = audiodelays_reverb_get_roomsize_fixedpoint(roomsize);
int16_t feedback = audiofreeverb_freeverb_get_roomsize_fixedpoint(roomsize);
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer;

View file

@ -11,7 +11,7 @@
#include "shared-module/synthio/__init__.h"
#include "shared-module/synthio/block.h"
extern const mp_obj_type_t audiodelays_reverb_type;
extern const mp_obj_type_t audiofreeverb_freeverb_type;
typedef struct {
audiosample_base_t base;
@ -39,18 +39,18 @@ typedef struct {
int16_t allpassbufferindex[8];
mp_obj_t sample;
} audiodelays_reverb_obj_t;
} audiofreeverb_freeverb_obj_t;
void audiodelays_reverb_reset_buffer(audiodelays_reverb_obj_t *self,
void audiofreeverb_freeverb_reset_buffer(audiofreeverb_freeverb_obj_t *self,
bool single_channel_output,
uint8_t channel);
audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj_t *self,
audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_freeverb_obj_t *self,
bool single_channel_output,
uint8_t channel,
uint8_t **buffer,
uint32_t *buffer_length); // length in bytes
int16_t audiodelays_reverb_get_roomsize_fixedpoint(mp_float_t n);
void audiodelays_reverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2);
void audiodelays_reverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect);
int16_t audiofreeverb_freeverb_get_roomsize_fixedpoint(mp_float_t n);
void audiofreeverb_freeverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2);
void audiofreeverb_freeverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect);

View file

@ -0,0 +1,5 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
//
// SPDX-License-Identifier: MIT

View file

@ -0,0 +1,7 @@
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
//
// SPDX-License-Identifier: MIT
#pragma once