Skip to content

Commit 4da22c5

Browse files
committed
Add mix parameter
1 parent ac5ccdb commit 4da22c5

File tree

4 files changed

+101
-34
lines changed

4 files changed

+101
-34
lines changed

shared-bindings/audiodelays/Echo.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,17 @@
1616
#include "shared-bindings/util.h"
1717

1818
#define DECAY_DEFAULT 0.7f
19+
#define MIX_DEFAULT 0.5f
1920

2021
//| class Echo:
2122
//| """An Echo effect"""
2223
//|
2324
static mp_obj_t audiodelays_echo_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
24-
enum { ARG_delay_ms, ARG_decay, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, };
25+
enum { ARG_delay_ms, ARG_decay, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, };
2526
static const mp_arg_t allowed_args[] = {
2627
{ MP_QSTR_delay_ms, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 50 } },
2728
{ MP_QSTR_decay, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
29+
{ MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} },
2830
{ MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} },
2931
{ MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} },
3032
{ MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} },
@@ -42,6 +44,11 @@ static mp_obj_t audiodelays_echo_make_new(const mp_obj_type_t *type, size_t n_ar
4244
: mp_obj_get_float(args[ARG_decay].u_obj);
4345
mp_arg_validate_float_range(decay, 0.0f, 1.0f, MP_QSTR_decay);
4446

47+
mp_float_t mix = (args[ARG_mix].u_obj == MP_OBJ_NULL)
48+
? (mp_float_t)MIX_DEFAULT
49+
: mp_obj_get_float(args[ARG_mix].u_obj);
50+
mp_arg_validate_float_range(mix, 0.0f, 1.0f, MP_QSTR_mix);
51+
4552
mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count);
4653
mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate);
4754
mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int;
@@ -50,7 +57,7 @@ static mp_obj_t audiodelays_echo_make_new(const mp_obj_type_t *type, size_t n_ar
5057
}
5158

5259
audiodelays_echo_obj_t *self = mp_obj_malloc(audiodelays_echo_obj_t, &audiodelays_echo_type);
53-
common_hal_audiodelays_echo_construct(self, delay_ms, decay, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
60+
common_hal_audiodelays_echo_construct(self, delay_ms, decay, mix, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate);
5461

5562
return MP_OBJ_FROM_PTR(self);
5663
}
@@ -120,8 +127,6 @@ MP_PROPERTY_GETSET(audiodelays_echo_delay_ms_obj,
120127
(mp_obj_t)&audiodelays_echo_get_delay_ms_obj,
121128
(mp_obj_t)&audiodelays_echo_set_delay_ms_obj);
122129

123-
124-
125130
//| decay: float
126131
//| """The rate the echo decays between 0 and 1."""
127132
static mp_obj_t audiodelays_echo_obj_get_decay(mp_obj_t self_in) {
@@ -139,10 +144,7 @@ static mp_obj_t audiodelays_echo_obj_set_decay(size_t n_args, const mp_obj_t *po
139144
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
140145

141146
mp_float_t decay = mp_obj_get_float(args[ARG_decay].u_obj);
142-
143-
if (decay > 1 || decay < 0) {
144-
mp_raise_ValueError(MP_ERROR_TEXT("decay must be between 0 and 1"));
145-
}
147+
mp_arg_validate_float_range(decay, 0.0f, 1.0f, MP_QSTR_decay);
146148

147149
common_hal_audiodelays_echo_set_decay(self, decay);
148150

@@ -155,6 +157,39 @@ MP_PROPERTY_GETSET(audiodelays_echo_decay_obj,
155157
(mp_obj_t)&audiodelays_echo_set_decay_obj);
156158

157159

160+
161+
162+
//| mix: float
163+
//| """The rate the echo mix between 0 and 1."""
164+
static mp_obj_t audiodelays_echo_obj_get_mix(mp_obj_t self_in) {
165+
return mp_obj_new_float(common_hal_audiodelays_echo_get_mix(self_in));
166+
}
167+
MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_mix_obj, audiodelays_echo_obj_get_mix);
168+
169+
static mp_obj_t audiodelays_echo_obj_set_mix(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
170+
enum { ARG_mix };
171+
static const mp_arg_t allowed_args[] = {
172+
{ MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_REQUIRED, {} },
173+
};
174+
audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
175+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
176+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
177+
178+
mp_float_t mix = mp_obj_get_float(args[ARG_mix].u_obj);
179+
mp_arg_validate_float_range(mix, 0.0f, 1.0f, MP_QSTR_mix);
180+
181+
common_hal_audiodelays_echo_set_mix(self, mix);
182+
183+
return mp_const_none;
184+
}
185+
MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_echo_set_mix_obj, 1, audiodelays_echo_obj_set_mix);
186+
187+
MP_PROPERTY_GETSET(audiodelays_echo_mix_obj,
188+
(mp_obj_t)&audiodelays_echo_get_mix_obj,
189+
(mp_obj_t)&audiodelays_echo_set_mix_obj);
190+
191+
192+
158193
//| playing: bool
159194
//| """True when any voice is being output. (read-only)"""
160195
static mp_obj_t audiodelays_echo_obj_get_playing(mp_obj_t self_in) {
@@ -196,7 +231,7 @@ static mp_obj_t audiodelays_echo_obj_play(size_t n_args, const mp_obj_t *pos_arg
196231
}
197232
MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_echo_play_obj, 1, audiodelays_echo_obj_play);
198233

199-
//| def stop_voice(self, voice: int = 0) -> None:
234+
//| def stop(self) -> None:
200235
//| """Stops playback of the sample."""
201236
//| ...
202237
//|
@@ -222,6 +257,7 @@ static const mp_rom_map_elem_t audiodelays_echo_locals_dict_table[] = {
222257
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_echo_playing_obj) },
223258
{ MP_ROM_QSTR(MP_QSTR_delay_ms), MP_ROM_PTR(&audiodelays_echo_delay_ms_obj) },
224259
{ MP_ROM_QSTR(MP_QSTR_decay), MP_ROM_PTR(&audiodelays_echo_decay_obj) },
260+
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_echo_mix_obj) },
225261
};
226262
static MP_DEFINE_CONST_DICT(audiodelays_echo_locals_dict, audiodelays_echo_locals_dict_table);
227263

shared-bindings/audiodelays/Echo.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
extern const mp_obj_type_t audiodelays_echo_type;
1212

1313
void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self,
14-
uint32_t delay_ms, mp_float_t decay,
14+
uint32_t delay_ms, mp_float_t decay, mp_float_t mix,
1515
uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed,
1616
uint8_t channel_count, uint32_t sample_rate);
1717

@@ -28,6 +28,9 @@ void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, uint
2828
mp_float_t common_hal_audiodelays_echo_get_decay(audiodelays_echo_obj_t *self);
2929
void common_hal_audiodelays_echo_set_decay(audiodelays_echo_obj_t *self, mp_float_t decay);
3030

31+
mp_float_t common_hal_audiodelays_echo_get_mix(audiodelays_echo_obj_t *self);
32+
void common_hal_audiodelays_echo_set_mix(audiodelays_echo_obj_t *self, mp_float_t decay);
33+
3134
bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self);
3235
void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sample, bool loop);
3336
void common_hal_audiodelays_echo_stop(audiodelays_echo_obj_t *self);

shared-module/audiodelays/Echo.c

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
#include "shared-module/audiomixer/utils.h"
1111

1212

13-
void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_t delay_ms, mp_float_t decay, uint32_t buffer_size, uint8_t bits_per_sample,
13+
void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_t delay_ms, mp_float_t decay, mp_float_t mix,
14+
uint32_t buffer_size, uint8_t bits_per_sample,
1415
bool samples_signed, uint8_t channel_count, uint32_t sample_rate) {
1516

1617
self->bits_per_sample = bits_per_sample;
@@ -28,6 +29,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
2829
memset(self->buffer, 0, self->buffer_len);
2930

3031
self->decay = (uint16_t)(decay * (1 << 15));
32+
self->mix = (uint16_t)(mix * (1 << 15));
3133

3234
// calculate buffer size for the set delay
3335
self->delay_ms = delay_ms;
@@ -101,6 +103,15 @@ void common_hal_audiodelays_echo_set_decay(audiodelays_echo_obj_t *self, mp_floa
101103
self->decay = (uint16_t)(decay * (1 << 15));
102104
}
103105

106+
mp_float_t common_hal_audiodelays_echo_get_mix(audiodelays_echo_obj_t *self) {
107+
return (mp_float_t)self->mix / (1 << 15);
108+
}
109+
110+
void common_hal_audiodelays_echo_set_mix(audiodelays_echo_obj_t *self, mp_float_t mix) {
111+
self->mix = (uint16_t)(mix * (1 << 15));
112+
mp_printf(&mp_plat_print, "mix %d\n", self->mix);
113+
}
114+
104115
uint32_t common_hal_audiodelays_echo_get_sample_rate(audiodelays_echo_obj_t *self) {
105116
return self->sample_rate;
106117
}
@@ -190,17 +201,25 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
190201
// If we have no sample keep the echo echoing
191202
if (self->sample == NULL) {
192203
if (MP_LIKELY(self->bits_per_sample == 16)) {
193-
// sample signed/unsigned won't matter as we have no sample
194-
for (uint32_t i = 0; i < length; i++) {
195-
uint32_t echo = self->echo_buffer[self->echo_buffer_read_pos++];
196-
word_buffer[i] = mult16signed(echo, self->decay);
197-
198-
self->echo_buffer[self->echo_buffer_write_pos++] = word_buffer[i];
199-
if (self->echo_buffer_read_pos >= echo_buf_len) {
200-
self->echo_buffer_read_pos = 0;
204+
if (self->mix == 0) { // no effect and no sample sound
205+
for (uint32_t i = 0; i < length; i++) {
206+
word_buffer[i] = 0;
201207
}
202-
if (self->echo_buffer_write_pos >= echo_buf_len) {
203-
self->echo_buffer_write_pos = 0;
208+
} else {
209+
// sample signed/unsigned won't matter as we have no sample
210+
for (uint32_t i = 0; i < length; i++) {
211+
uint32_t echo = self->echo_buffer[self->echo_buffer_read_pos++];
212+
word_buffer[i] = mult16signed(echo, self->decay);
213+
self->echo_buffer[self->echo_buffer_write_pos++] = word_buffer[i];
214+
215+
word_buffer[i] = mult16signed(word_buffer[i], self->mix);
216+
217+
if (self->echo_buffer_read_pos >= echo_buf_len) {
218+
self->echo_buffer_read_pos = 0;
219+
}
220+
if (self->echo_buffer_write_pos >= echo_buf_len) {
221+
self->echo_buffer_write_pos = 0;
222+
}
204223
}
205224

206225
}
@@ -227,20 +246,28 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
227246
uint32_t *sample_src = self->sample_remaining_buffer;
228247

229248
if (MP_LIKELY(self->bits_per_sample == 16)) {
230-
for (uint32_t i = 0; i < n; i++) {
231-
uint32_t sample_word = sample_src[i];
232-
if (MP_LIKELY(!self->samples_signed)) {
233-
sample_word = tosigned16(sample_word);
249+
if (self->mix == 0) { // sample only
250+
for (uint32_t i = 0; i < n; i++) {
251+
word_buffer[i] = sample_src[i];
234252
}
235-
uint32_t echo = self->echo_buffer[self->echo_buffer_read_pos++];
236-
word_buffer[i] = add16signed(mult16signed(echo, self->decay), sample_word);
237-
self->echo_buffer[self->echo_buffer_write_pos++] = word_buffer[i];
238-
239-
if (self->echo_buffer_read_pos >= echo_buf_len) {
240-
self->echo_buffer_read_pos = 0;
241-
}
242-
if (self->echo_buffer_write_pos >= echo_buf_len) {
243-
self->echo_buffer_write_pos = 0;
253+
} else {
254+
for (uint32_t i = 0; i < n; i++) {
255+
uint32_t sample_word = sample_src[i];
256+
if (MP_LIKELY(!self->samples_signed)) {
257+
sample_word = tosigned16(sample_word);
258+
}
259+
uint32_t echo = self->echo_buffer[self->echo_buffer_read_pos++];
260+
word_buffer[i] = add16signed(mult16signed(echo, self->decay), sample_word);
261+
self->echo_buffer[self->echo_buffer_write_pos++] = word_buffer[i];
262+
263+
word_buffer[i] = add16signed(mult16signed(sample_word, 32768 - self->mix), mult16signed(word_buffer[i], self->mix));
264+
265+
if (self->echo_buffer_read_pos >= echo_buf_len) {
266+
self->echo_buffer_read_pos = 0;
267+
}
268+
if (self->echo_buffer_write_pos >= echo_buf_len) {
269+
self->echo_buffer_write_pos = 0;
270+
}
244271
}
245272
}
246273
} else { // bits per sample is 8

shared-module/audiodelays/Echo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ typedef struct {
1515
mp_obj_base_t base;
1616
uint32_t delay_ms;
1717
uint16_t decay;
18+
uint16_t mix;
1819
uint8_t bits_per_sample;
1920
bool samples_signed;
2021
uint8_t channel_count;

0 commit comments

Comments
 (0)