Skip to content

Commit f8afdcb

Browse files
committed
Add audiodelays & audioeffects to unix coverage port
.. and add a very basic audioeffects test, showing that it plausibly is working I had to address several build errors that occurred in the Unix build, mostly related to conversion from FP types to integral types (replaced by explicit casts) and by accidental mixing of regular & f-suffixed floating constants (replaced with the MICROPY_FLOAT_CONST macro) Particularly this change could use consideration: ```diff - self->max_echo_buffer_len = self->sample_rate / 1000.0f * max_delay_ms * (self->channel_count * sizeof(uint16_t)); // bytes + self->max_echo_buffer_len = (uint32_t)(self->sample_rate / 1000.0f * max_delay_ms) * (self->channel_count * sizeof(uint16_t)); // bytes ``` The buffer length is being calculated in floating point based on the millisecond delay & the sample rate. The result could then be a fractional number such as 529.2 for a 12ms delay at 44.1kHz. Multiplying a floating number by the size required for each echo buffer item (`(self->channel_count * sizeof(uint16_t))`) could yield a number of bytes that doesn't correspond to an integral number of buffer items. I grouped the float->int conversion so that it converts the number of echo buffer items to an integer and then multiplies by the size of the item.
1 parent 3a0b97d commit f8afdcb

File tree

6 files changed

+1603
-13
lines changed

6 files changed

+1603
-13
lines changed

ports/unix/variants/coverage/mpconfigvariant.mk

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ SRC_BITMAP := \
3333
shared-bindings/audiocore/__init__.c \
3434
shared-bindings/audiocore/RawSample.c \
3535
shared-bindings/audiocore/WaveFile.c \
36+
shared-bindings/audiodelays/Echo.c \
37+
shared-bindings/audiodelays/__init__.c \
38+
shared-bindings/audiofilters/Filter.c \
39+
shared-bindings/audiofilters/__init__.c \
3640
shared-bindings/audiomixer/__init__.c \
3741
shared-bindings/audiomixer/Mixer.c \
3842
shared-bindings/audiomixer/MixerVoice.c \
@@ -70,6 +74,10 @@ SRC_BITMAP := \
7074
shared-module/audiocore/__init__.c \
7175
shared-module/audiocore/RawSample.c \
7276
shared-module/audiocore/WaveFile.c \
77+
shared-module/audiodelays/Echo.c \
78+
shared-module/audiodelays/__init__.c \
79+
shared-module/audiofilters/Filter.c \
80+
shared-module/audiofilters/__init__.c \
7381
shared-module/audiomixer/__init__.c \
7482
shared-module/audiomp3/MP3Decoder.c \
7583
shared-module/audiomixer/Mixer.c \
@@ -127,6 +135,9 @@ $(BUILD)/lib/mp3/src/buffers.o: CFLAGS += -include "shared-module/audiomp3/__ini
127135
CFLAGS += \
128136
-DCIRCUITPY_AESIO=1 \
129137
-DCIRCUITPY_AUDIOCORE=1 \
138+
-DCIRCUITPY_AUDIOEFFECTS=1 \
139+
-DCIRCUITPY_AUDIODELAYS=1 \
140+
-DCIRCUITPY_AUDIOFILTERS=1 \
130141
-DCIRCUITPY_AUDIOMIXER=1 \
131142
-DCIRCUITPY_AUDIOMP3=1 \
132143
-DCIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR=0 \

shared-module/audiodelays/Echo.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
7777

7878
// Allocate the echo buffer for the max possible delay, echo is always 16-bit
7979
self->max_delay_ms = max_delay_ms;
80-
self->max_echo_buffer_len = self->sample_rate / 1000.0f * max_delay_ms * (self->channel_count * sizeof(uint16_t)); // bytes
80+
self->max_echo_buffer_len = (uint32_t)(self->sample_rate / 1000.0f * max_delay_ms) * (self->channel_count * sizeof(uint16_t)); // bytes
8181
self->echo_buffer = m_malloc(self->max_echo_buffer_len);
8282
if (self->echo_buffer == NULL) {
8383
common_hal_audiodelays_echo_deinit(self);
@@ -129,11 +129,11 @@ void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, mp_o
129129
void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
130130
if (self->freq_shift) {
131131
// Calculate the rate of iteration over the echo buffer with 8 sub-bits
132-
self->echo_buffer_rate = MAX(self->max_delay_ms / f_delay_ms * 256.0f, 1.0);
132+
self->echo_buffer_rate = (uint32_t)MAX(self->max_delay_ms / f_delay_ms * MICROPY_FLOAT_CONST(256.0), MICROPY_FLOAT_CONST(1.0));
133133
self->echo_buffer_len = self->max_echo_buffer_len;
134134
} else {
135135
// Calculate the current echo buffer length in bytes
136-
uint32_t new_echo_buffer_len = self->sample_rate / 1000.0f * f_delay_ms * (self->channel_count * sizeof(uint16_t));
136+
uint32_t new_echo_buffer_len = (uint32_t)(self->sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * (self->channel_count * sizeof(uint16_t));
137137

138138
// Check if our new echo is too long for our maximum buffer
139139
if (new_echo_buffer_len > self->max_echo_buffer_len) {
@@ -153,7 +153,7 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
153153
memset(self->echo_buffer + self->echo_buffer_len, 0, self->max_echo_buffer_len - self->echo_buffer_len);
154154
}
155155

156-
self->current_delay_ms = f_delay_ms;
156+
self->current_delay_ms = (uint32_t)f_delay_ms;
157157
}
158158

159159
mp_obj_t common_hal_audiodelays_echo_get_decay(audiodelays_echo_obj_t *self) {
@@ -360,17 +360,17 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
360360
echo = echo_buffer[echo_buffer_pos >> 8];
361361
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
362362

363-
word = echo * decay;
363+
word = (int16_t)(echo * decay);
364364
for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) {
365365
echo_buffer[j % echo_buf_len] = word;
366366
}
367367
} else {
368368
echo = echo_buffer[self->echo_buffer_read_pos++];
369-
word = echo * decay;
369+
word = (int16_t)(echo * decay);
370370
echo_buffer[self->echo_buffer_write_pos++] = word;
371371
}
372372

373-
word = echo * mix;
373+
word = (int16_t)(echo * mix);
374374

375375
if (MP_LIKELY(self->bits_per_sample == 16)) {
376376
word_buffer[i] = word;
@@ -433,10 +433,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
433433
if (self->freq_shift) {
434434
echo = echo_buffer[echo_buffer_pos >> 8];
435435
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
436-
word = echo * decay + sample_word;
436+
word = (int32_t)(echo * decay + sample_word);
437437
} else {
438438
echo = echo_buffer[self->echo_buffer_read_pos++];
439-
word = echo * decay + sample_word;
439+
word = (int32_t)(echo * decay + sample_word);
440440
}
441441

442442
if (MP_LIKELY(self->bits_per_sample == 16)) {
@@ -467,12 +467,12 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
467467
word = echo + sample_word;
468468

469469
if (MP_LIKELY(self->bits_per_sample == 16)) {
470-
word_buffer[i] = (sample_word * (1.0 - mix)) + (word * mix);
470+
word_buffer[i] = (int16_t)((sample_word * (1.0 - mix)) + (word * mix));
471471
if (!self->samples_signed) {
472472
word_buffer[i] ^= 0x8000;
473473
}
474474
} else {
475-
int8_t mixed = (sample_word * (1.0 - mix)) + (word * mix);
475+
int8_t mixed = (int16_t)((sample_word * (1.0 - mix)) + (word * mix));
476476
if (self->samples_signed) {
477477
hword_buffer[i] = mixed;
478478
} else {

shared-module/audiofilters/Filter.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ int16_t mix_down_sample(int32_t sample) {
204204

205205
audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self, bool single_channel_output, uint8_t channel,
206206
uint8_t **buffer, uint32_t *buffer_length) {
207+
(void)channel;
207208

208209
if (!single_channel_output) {
209210
channel = 0;
@@ -297,15 +298,15 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
297298
// Mix processed signal with original sample and transfer to output buffer
298299
for (uint32_t j = 0; j < n_samples; j++) {
299300
if (MP_LIKELY(self->bits_per_sample == 16)) {
300-
word_buffer[i + j] = mix_down_sample((sample_src[i + j] * (1.0 - mix)) + (self->filter_buffer[j] * mix));
301+
word_buffer[i + j] = mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)));
301302
if (!self->samples_signed) {
302303
word_buffer[i + j] ^= 0x8000;
303304
}
304305
} else {
305306
if (self->samples_signed) {
306307
hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (1.0 - mix)) + (self->filter_buffer[j] * mix));
307308
} else {
308-
hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (1.0 - mix)) + (self->filter_buffer[j] * mix)) ^ 0x80;
309+
hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)) ^ 0x80;
309310
}
310311
}
311312
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from audiofilters import Filter
2+
from audiofilterhelper import synth_test, sine8k
3+
4+
@synth_test
5+
def basic_filter():
6+
effect = Filter(
7+
bits_per_sample=16,
8+
samples_signed=True,
9+
)
10+
yield effect, []
11+
12+
effect.play(sine8k, loop=True)
13+
yield 4
14+
15+
effect.stop()
16+
yield 2

0 commit comments

Comments
 (0)