Skip to content

Commit aba78f9

Browse files
committed
Initial buffers
1 parent a405019 commit aba78f9

File tree

4 files changed

+246
-8
lines changed

4 files changed

+246
-8
lines changed

shared-bindings/audiodelays/Reverb.c

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,16 @@
7979
//| ...
8080
//|
8181
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) {
82-
enum { ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, ARG_freq_shift, };
82+
enum { ARG_roomsize, ARG_damp, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, };
8383
static const mp_arg_t allowed_args[] = {
84+
{ MP_QSTR_roomsize, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
85+
{ MP_QSTR_damp, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
86+
{ MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
8487
{ MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} },
8588
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} },
8689
{ MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
8790
{ MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} },
8891
{ MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } },
89-
{ MP_QSTR_freq_shift, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true } },
9092
};
9193

9294
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -103,7 +105,7 @@ static mp_obj_t audiodelays_reverb_make_new(const mp_obj_type_t *type, size_t n_
103105
}
104106

105107
audiodelays_reverb_obj_t *self = mp_obj_malloc(audiodelays_reverb_obj_t, &audiodelays_reverb_type);
106-
common_hal_audiodelays_reverb_construct(self, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate, args[ARG_freq_shift].u_bool);
108+
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);
107109

108110
return MP_OBJ_FROM_PTR(self);
109111
}
@@ -136,6 +138,60 @@ static void check_for_deinit(audiodelays_reverb_obj_t *self) {
136138
//|
137139
// Provided by context manager helper.
138140

141+
//| roomsize: synthio.BlockInput
142+
//| """TODO. Apparent roomsize 0.0-1.0"""
143+
static mp_obj_t audiodelays_reverb_obj_get_roomsize(mp_obj_t self_in) {
144+
return common_hal_audiodelays_reverb_get_roomsize(self_in);
145+
}
146+
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_roomsize_obj, audiodelays_reverb_obj_get_roomsize);
147+
148+
static mp_obj_t audiodelays_reverb_obj_set_roomsize(mp_obj_t self_in, mp_obj_t roomsize) {
149+
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
150+
common_hal_audiodelays_reverb_set_roomsize(self, roomsize);
151+
return mp_const_none;
152+
}
153+
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_roomsize_obj, audiodelays_reverb_obj_set_roomsize);
154+
155+
MP_PROPERTY_GETSET(audiodelays_reverb_roomsize_obj,
156+
(mp_obj_t)&audiodelays_reverb_get_roomsize_obj,
157+
(mp_obj_t)&audiodelays_reverb_set_roomsize_obj);
158+
159+
//| damp: synthio.BlockInput
160+
//| """TODO. How reverbrent the area is. 0.0-1.0"""
161+
static mp_obj_t audiodelays_reverb_obj_get_damp(mp_obj_t self_in) {
162+
return common_hal_audiodelays_reverb_get_damp(self_in);
163+
}
164+
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_damp_obj, audiodelays_reverb_obj_get_damp);
165+
166+
static mp_obj_t audiodelays_reverb_obj_set_damp(mp_obj_t self_in, mp_obj_t damp) {
167+
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
168+
common_hal_audiodelays_reverb_set_damp(self, damp);
169+
return mp_const_none;
170+
}
171+
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_damp_obj, audiodelays_reverb_obj_set_damp);
172+
173+
MP_PROPERTY_GETSET(audiodelays_reverb_damp_obj,
174+
(mp_obj_t)&audiodelays_reverb_get_damp_obj,
175+
(mp_obj_t)&audiodelays_reverb_set_damp_obj);
176+
177+
//| mix: synthio.BlockInput
178+
//| """The rate the reverb mix between 0 and 1 where 0 is only sample and 1 is all effect."""
179+
static mp_obj_t audiodelays_reverb_obj_get_mix(mp_obj_t self_in) {
180+
return common_hal_audiodelays_reverb_get_mix(self_in);
181+
}
182+
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_reverb_get_mix_obj, audiodelays_reverb_obj_get_mix);
183+
184+
static mp_obj_t audiodelays_reverb_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) {
185+
audiodelays_reverb_obj_t *self = MP_OBJ_TO_PTR(self_in);
186+
common_hal_audiodelays_reverb_set_mix(self, mix_in);
187+
return mp_const_none;
188+
}
189+
MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_reverb_set_mix_obj, audiodelays_reverb_obj_set_mix);
190+
191+
MP_PROPERTY_GETSET(audiodelays_reverb_mix_obj,
192+
(mp_obj_t)&audiodelays_reverb_get_mix_obj,
193+
(mp_obj_t)&audiodelays_reverb_set_mix_obj);
194+
139195
//| playing: bool
140196
//| """True when the effect is playing a sample. (read-only)"""
141197
//|
@@ -198,6 +254,9 @@ static const mp_rom_map_elem_t audiodelays_reverb_locals_dict_table[] = {
198254

199255
// Properties
200256
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_reverb_playing_obj) },
257+
{ MP_ROM_QSTR(MP_QSTR_roomsize), MP_ROM_PTR(&audiodelays_reverb_roomsize_obj) },
258+
{ MP_ROM_QSTR(MP_QSTR_damp), MP_ROM_PTR(&audiodelays_reverb_damp_obj) },
259+
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_reverb_mix_obj) },
201260
AUDIOSAMPLE_FIELDS,
202261
};
203262
static MP_DEFINE_CONST_DICT(audiodelays_reverb_locals_dict, audiodelays_reverb_locals_dict_table);

shared-bindings/audiodelays/Reverb.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
extern const mp_obj_type_t audiodelays_reverb_type;
1212

1313
void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self,
14+
mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
1415
uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed,
15-
uint8_t channel_count, uint32_t sample_rate, bool freq_shift);
16+
uint8_t channel_count, uint32_t sample_rate);
1617

1718
void common_hal_audiodelays_reverb_deinit(audiodelays_reverb_obj_t *self);
1819
bool common_hal_audiodelays_reverb_deinited(audiodelays_reverb_obj_t *self);
@@ -21,6 +22,15 @@ uint32_t common_hal_audiodelays_reverb_get_sample_rate(audiodelays_reverb_obj_t
2122
uint8_t common_hal_audiodelays_reverb_get_channel_count(audiodelays_reverb_obj_t *self);
2223
uint8_t common_hal_audiodelays_reverb_get_bits_per_sample(audiodelays_reverb_obj_t *self);
2324

25+
mp_obj_t common_hal_audiodelays_reverb_get_roomsize(audiodelays_reverb_obj_t *self);
26+
void common_hal_audiodelays_reverb_set_roomsize(audiodelays_reverb_obj_t *self, mp_obj_t feedback);
27+
28+
mp_obj_t common_hal_audiodelays_reverb_get_damp(audiodelays_reverb_obj_t *self);
29+
void common_hal_audiodelays_reverb_set_damp(audiodelays_reverb_obj_t *self, mp_obj_t damp);
30+
31+
mp_obj_t common_hal_audiodelays_reverb_get_mix(audiodelays_reverb_obj_t *self);
32+
void common_hal_audiodelays_reverb_set_mix(audiodelays_reverb_obj_t *self, mp_obj_t mix);
33+
2434
bool common_hal_audiodelays_reverb_get_playing(audiodelays_reverb_obj_t *self);
2535
void common_hal_audiodelays_reverb_play(audiodelays_reverb_obj_t *self, mp_obj_t sample, bool loop);
2636
void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self);

shared-module/audiodelays/Reverb.c

Lines changed: 158 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
#include "py/runtime.h"
1010
#include <math.h>
1111

12-
void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self,
12+
void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self, mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix,
1313
uint32_t buffer_size, uint8_t bits_per_sample,
14-
bool samples_signed, uint8_t channel_count, uint32_t sample_rate, bool freq_shift) {
14+
bool samples_signed, uint8_t channel_count, uint32_t sample_rate) {
1515

1616
// Basic settings every effect and audio sample has
1717
// These are the effects values, not the source sample(s)
@@ -53,6 +53,60 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self,
5353
self->more_data = false; // Is there still more data to read from the sample or did we finish
5454

5555
// The below section sets up the reverb effect's starting values. For a different effect this section will change
56+
if (roomsize == MP_OBJ_NULL) {
57+
roomsize = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
58+
}
59+
synthio_block_assign_slot(roomsize, &self->roomsize, MP_QSTR_roomsize);
60+
common_hal_audiodelays_reverb_set_roomsize(self, roomsize);
61+
62+
if (damp == MP_OBJ_NULL) {
63+
damp = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
64+
}
65+
synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp);
66+
common_hal_audiodelays_reverb_set_damp(self, damp);
67+
68+
if (mix == MP_OBJ_NULL) {
69+
mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5));
70+
}
71+
synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix);
72+
common_hal_audiodelays_reverb_set_mix(self, mix);
73+
74+
// Set up the comb filters
75+
self->combbuffersizes[0] = 1116;
76+
self->combbuffersizes[1] = 1188;
77+
self->combbuffersizes[2] = 1277;
78+
self->combbuffersizes[3] = 1356;
79+
self->combbuffersizes[4] = 1422;
80+
self->combbuffersizes[5] = 1491;
81+
self->combbuffersizes[6] = 1557;
82+
self->combbuffersizes[7] = 1617;
83+
for (uint32_t i = 0; i < 8; i++) {
84+
self->combbuffers[i] = m_malloc(self->combbuffersizes[i] * sizeof(uint16_t));
85+
if (self->combbuffers[i] == NULL) {
86+
common_hal_audiodelays_reverb_deinit(self);
87+
m_malloc_fail(self->combbuffersizes[i]);
88+
}
89+
memset(self->combbuffers[i], 0, self->combbuffersizes[i]);
90+
91+
self->combbufferindex[i] = 0;
92+
self->combfitlers[i] = 0;
93+
}
94+
95+
// Set up the allpass filters
96+
self->allpassbuffersizes[0] = 556;
97+
self->allpassbuffersizes[1] = 441;
98+
self->allpassbuffersizes[2] = 341;
99+
self->allpassbuffersizes[3] = 225;
100+
for (uint32_t i = 0; i < 4; i++) {
101+
self->allpassbuffers[i] = m_malloc(self->allpassbuffersizes[i] * sizeof(uint16_t));
102+
if (self->allpassbuffers[i] == NULL) {
103+
common_hal_audiodelays_reverb_deinit(self);
104+
m_malloc_fail(self->allpassbuffersizes[i]);
105+
}
106+
memset(self->allpassbuffers[i], 0, self->allpassbuffersizes[i]);
107+
108+
self->allpassbufferindex[i] = 0;
109+
}
56110
}
57111

58112
bool common_hal_audiodelays_reverb_deinited(audiodelays_reverb_obj_t *self) {
@@ -70,6 +124,51 @@ void common_hal_audiodelays_reverb_deinit(audiodelays_reverb_obj_t *self) {
70124
self->buffer[1] = NULL;
71125
}
72126

127+
mp_obj_t common_hal_audiodelays_reverb_get_roomsize(audiodelays_reverb_obj_t *self) {
128+
return self->roomsize.obj;
129+
}
130+
131+
void common_hal_audiodelays_reverb_set_roomsize(audiodelays_reverb_obj_t *self, mp_obj_t roomsize_obj) {
132+
synthio_block_assign_slot(roomsize_obj, &self->roomsize, MP_QSTR_roomsize);
133+
}
134+
135+
int16_t audiodelays_reverb_get_roomsize_fixedpoint(mp_float_t n) {
136+
if (n > 1.0f) {
137+
n = 1.0f;
138+
} else if (n < 0.0f) {
139+
n = 0.0f;
140+
}
141+
142+
return (int16_t)(n * 9175.04f) + 22937; // 9175.04 = 0.28f in fixed point 22937 = 0.7f
143+
}
144+
145+
mp_obj_t common_hal_audiodelays_reverb_get_damp(audiodelays_reverb_obj_t *self) {
146+
return self->damp.obj;
147+
}
148+
149+
void common_hal_audiodelays_reverb_set_damp(audiodelays_reverb_obj_t *self, mp_obj_t damp) {
150+
synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp);
151+
}
152+
153+
void audiodelays_reverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2) {
154+
if (n > 1.0f) {
155+
n = 1.0f;
156+
} else if (n < 0.0f) {
157+
n = 0.0f;
158+
}
159+
160+
*damp1 = (int16_t)(n * 13107.2f); // 13107.2 = 0.4f scaling factor
161+
*damp2 = (int16_t)(32768 - *damp1); // inverse of x1 damp2 = 1.0 - damp1
162+
}
163+
164+
mp_obj_t common_hal_audiodelays_reverb_get_mix(audiodelays_reverb_obj_t *self) {
165+
return self->mix.obj;
166+
}
167+
168+
void common_hal_audiodelays_reverb_set_mix(audiodelays_reverb_obj_t *self, mp_obj_t mix) {
169+
synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix);
170+
}
171+
73172
void audiodelays_reverb_reset_buffer(audiodelays_reverb_obj_t *self,
74173
bool single_channel_output,
75174
uint8_t channel) {
@@ -106,6 +205,27 @@ void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self) {
106205
return;
107206
}
108207

208+
// cleaner sat16 by http://www.moseleyinstruments.com/
209+
static int16_t sat16(int32_t n, int rshift) {
210+
// we should always round towards 0
211+
// to avoid recirculating round-off noise
212+
//
213+
// a 2s complement positive number is always
214+
// rounded down, so we only need to take
215+
// care of negative numbers
216+
if (n < 0) {
217+
n = n + (~(0xFFFFFFFFUL << rshift));
218+
}
219+
n = n >> rshift;
220+
if (n > 32767) {
221+
return 32767;
222+
}
223+
if (n < -32768) {
224+
return -32768;
225+
}
226+
return n;
227+
}
228+
109229
audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj_t *self, bool single_channel_output, uint8_t channel,
110230
uint8_t **buffer, uint32_t *buffer_length) {
111231

@@ -150,6 +270,12 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
150270

151271
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
152272
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
273+
mp_float_t damp = synthio_block_slot_get_limited(&self->damp, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
274+
int16_t damp1, damp2;
275+
audiodelays_reverb_get_damp_fixedpoint(damp, &damp1, &damp2);
276+
277+
mp_float_t roomsize = synthio_block_slot_get_limited(&self->roomsize, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
278+
int16_t feedback = audiodelays_reverb_get_roomsize_fixedpoint(roomsize);
153279

154280
// If we have no sample keep the reverb reverbing
155281
if (self->sample == NULL) {
@@ -164,10 +290,38 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
164290

165291
for (uint32_t i = 0; i < n; i++) {
166292
int32_t sample_word = sample_src[i];
167-
168293
int32_t word;
169-
word = synthio_mix_down_sample(sample_word, SYNTHIO_MIX_DOWN_SCALE(2));
294+
int16_t input, bufout, output;
295+
int32_t sum;
296+
297+
input = sat16(sample_word * 8738, 17);
298+
sum = 0;
299+
300+
for (uint32_t j = 0; j < 8; j++) {
301+
bufout = self->combbuffers[j][self->combbufferindex[j]];
302+
sum += bufout;
303+
self->combfitlers[j] = sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15);
304+
self->combbuffers[j][self->combbufferindex[j]] = sat16(input + sat16(self->combfitlers[j] * feedback, 15), 0);
305+
if (++self->combbufferindex[j] >= self->combbuffersizes[j]) {
306+
self->combbufferindex[j] = 0;
307+
}
308+
}
309+
310+
output = sat16(sum * 31457, 17); // 31457 = 0.96f
170311

312+
for (uint32_t j = 0; j < 4; j++) {
313+
bufout = self->allpassbuffers[j][self->allpassbufferindex[j]];
314+
self->allpassbuffers[j][self->allpassbufferindex[j]] = output + (bufout >> 1); // bufout >> 1 same as bufout*0.5f
315+
output = sat16(bufout - output, 1);
316+
if (++self->allpassbufferindex[j] >= self->allpassbuffersizes[j]) {
317+
self->allpassbufferindex[j] = 0;
318+
}
319+
}
320+
321+
word = sat16(output * 30, 0);
322+
323+
324+
word = synthio_mix_down_sample(sample_word, SYNTHIO_MIX_DOWN_SCALE(2));
171325
word_buffer[i] = (int16_t)word;
172326
}
173327

shared-module/audiodelays/Reverb.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ extern const mp_obj_type_t audiodelays_reverb_type;
1515

1616
typedef struct {
1717
audiosample_base_t base;
18+
synthio_block_slot_t roomsize;
19+
synthio_block_slot_t damp;
20+
synthio_block_slot_t mix;
1821

1922
int8_t *buffer[2];
2023
uint8_t last_buf_idx;
@@ -26,6 +29,15 @@ typedef struct {
2629
bool loop;
2730
bool more_data;
2831

32+
int16_t combbuffersizes[8];
33+
int16_t *combbuffers[8];
34+
int16_t combbufferindex[8];
35+
int16_t combfitlers[8];
36+
37+
int16_t allpassbuffersizes[4];
38+
int16_t *allpassbuffers[4];
39+
int16_t allpassbufferindex[4];
40+
2941
mp_obj_t sample;
3042
} audiodelays_reverb_obj_t;
3143

@@ -38,3 +50,6 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
3850
uint8_t channel,
3951
uint8_t **buffer,
4052
uint32_t *buffer_length); // length in bytes
53+
54+
int16_t audiodelays_reverb_get_roomsize_fixedpoint(mp_float_t n);
55+
void audiodelays_reverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2);

0 commit comments

Comments
 (0)