Skip to content

Commit 7d0e72e

Browse files
committed
Unify echo buffer channel splitting.
1 parent feee74a commit 7d0e72e

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

shared-module/audiodelays/Echo.c

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
9898

9999
// read is where we read previous echo from delay_ms ago to play back now
100100
// write is where the store the latest playing sample to echo back later
101-
self->echo_buffer_pos = 0;
101+
self->echo_buffer_left_pos = 0;
102102

103-
// use a separate buffer position for the right channel when using freq_shift
103+
// use a separate buffer position for the right channel
104104
self->echo_buffer_right_pos = 0;
105105
}
106106

@@ -127,18 +127,21 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
127127
// Require that delay is at least 1 sample long
128128
f_delay_ms = MAX(f_delay_ms, self->sample_ms);
129129

130+
// Calculate the maximum buffer size per channel in bytes
131+
uint32_t max_echo_buffer_len = self->max_echo_buffer_len >> (self->base.channel_count - 1);
132+
130133
if (self->freq_shift) {
131134
// Calculate the rate of iteration over the echo buffer with 8 sub-bits
132135
self->echo_buffer_rate = (uint32_t)MAX(self->max_delay_ms / f_delay_ms * MICROPY_FLOAT_CONST(256.0), MICROPY_FLOAT_CONST(1.0));
133136
// Only use half of the buffer per channel if stereo
134-
self->echo_buffer_len = self->max_echo_buffer_len >> (self->base.channel_count - 1);
137+
self->echo_buffer_len = max_echo_buffer_len;
135138
} else {
136139
// Calculate the current echo buffer length in bytes
137-
uint32_t new_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * (self->base.channel_count * sizeof(uint16_t));
140+
uint32_t new_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * sizeof(uint16_t);
138141

139142
// Limit to valid range
140-
if (new_echo_buffer_len > self->max_echo_buffer_len) {
141-
new_echo_buffer_len = self->max_echo_buffer_len;
143+
if (new_echo_buffer_len > max_echo_buffer_len) {
144+
new_echo_buffer_len = max_echo_buffer_len;
142145
} else if (new_echo_buffer_len < self->buffer_len) {
143146
// If the echo buffer is smaller than our audio buffer, weird things happen
144147
new_echo_buffer_len = self->buffer_len;
@@ -147,7 +150,9 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
147150
self->echo_buffer_len = new_echo_buffer_len;
148151

149152
// Clear the now unused part of the buffer or some weird artifacts appear
150-
memset(self->echo_buffer + self->echo_buffer_len, 0, self->max_echo_buffer_len - self->echo_buffer_len);
153+
for (uint32_t i = 0; i < self->base.channel_count; i++) {
154+
memset(self->echo_buffer + (i * max_echo_buffer_len) + self->echo_buffer_len, 0, max_echo_buffer_len - self->echo_buffer_len);
155+
}
151156
}
152157

153158
self->current_delay_ms = f_delay_ms;
@@ -177,7 +182,7 @@ void common_hal_audiodelays_echo_set_freq_shift(audiodelays_echo_obj_t *self, bo
177182
// Clear the echo buffer and reset buffer position if changing freq_shift modes
178183
if (self->freq_shift != freq_shift) {
179184
memset(self->echo_buffer, 0, self->max_echo_buffer_len);
180-
self->echo_buffer_pos = 0;
185+
self->echo_buffer_left_pos = 0;
181186
self->echo_buffer_right_pos = 0;
182187
}
183188
self->freq_shift = freq_shift;
@@ -279,12 +284,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
279284
}
280285

281286
uint32_t echo_buf_len = self->echo_buffer_len / sizeof(uint16_t);
282-
283-
// Set our echo buffer position accounting for stereo
284-
uint32_t echo_buffer_pos = self->echo_buffer_pos;
285-
if (self->freq_shift && channel == 1) {
286-
echo_buffer_pos = self->echo_buffer_right_pos;
287-
}
287+
uint32_t max_echo_buf_len = (self->max_echo_buffer_len >> (self->base.channel_count - 1)) / sizeof(uint16_t);
288288

289289
// If we have no sample keep the echo echoing
290290
if (self->sample == NULL) {
@@ -307,7 +307,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
307307
for (uint32_t i = 0; i < length; i++) {
308308
int16_t echo, word = 0;
309309
uint32_t next_buffer_pos = 0;
310-
uint32_t echo_buffer_offset = echo_buf_len * (self->freq_shift && ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1)));
310+
311+
// Get our echo buffer position and offset depending on current channel
312+
uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1));
313+
uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos;
311314

312315
if (self->freq_shift) {
313316
echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset];
@@ -318,9 +321,9 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
318321
echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = word;
319322
}
320323
} else {
321-
echo = echo_buffer[echo_buffer_pos];
324+
echo = echo_buffer[echo_buffer_pos + echo_buffer_offset];
322325
word = (int16_t)(echo * decay);
323-
echo_buffer[echo_buffer_pos++] = word;
326+
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = word;
324327
}
325328

326329
word = (int16_t)(echo * mix);
@@ -337,11 +340,18 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
337340
}
338341
}
339342

340-
if (self->freq_shift && (self->base.channel_count == 1 || single_channel_output || (!single_channel_output && (i % self->base.channel_count) == 1))) {
343+
if (self->freq_shift) {
341344
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
342345
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
343346
echo_buffer_pos = 0;
344347
}
348+
349+
// Update buffer position
350+
if (echo_buffer_offset) {
351+
self->echo_buffer_right_pos = echo_buffer_pos;
352+
} else {
353+
self->echo_buffer_left_pos = echo_buffer_pos;
354+
}
345355
}
346356
}
347357

@@ -375,13 +385,16 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
375385

376386
int32_t echo, word = 0;
377387
uint32_t next_buffer_pos = 0;
378-
uint32_t echo_buffer_offset = echo_buf_len * (self->freq_shift && ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1)));
388+
389+
// Get our echo buffer position and offset depending on current channel
390+
uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1));
391+
uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos;
379392

380393
if (self->freq_shift) {
381394
echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset];
382395
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
383396
} else {
384-
echo = echo_buffer[echo_buffer_pos];
397+
echo = echo_buffer[echo_buffer_pos + echo_buffer_offset];
385398
word = (int32_t)(echo * decay + sample_word);
386399
}
387400

@@ -394,7 +407,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
394407
}
395408
} else {
396409
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
397-
echo_buffer[echo_buffer_pos++] = (int16_t)word;
410+
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int16_t)word;
398411
}
399412
} else {
400413
if (self->freq_shift) {
@@ -407,7 +420,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
407420
} else {
408421
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
409422
word = MIN(MAX(word, -128), 127);
410-
echo_buffer[echo_buffer_pos++] = (int8_t)word;
423+
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int8_t)word;
411424
}
412425
}
413426

@@ -428,11 +441,18 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
428441
}
429442
}
430443

431-
if (self->freq_shift && (self->base.channel_count == 1 || single_channel_output || (!single_channel_output && (i % self->base.channel_count) == 1))) {
444+
if (self->freq_shift) {
432445
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
433446
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
434447
echo_buffer_pos = 0;
435448
}
449+
450+
// Update buffer position
451+
if (echo_buffer_offset) {
452+
self->echo_buffer_right_pos = echo_buffer_pos;
453+
} else {
454+
self->echo_buffer_left_pos = echo_buffer_pos;
455+
}
436456
}
437457
}
438458

@@ -443,13 +463,6 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
443463
self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8));
444464
self->sample_buffer_length -= n;
445465
}
446-
447-
// Update buffer position
448-
if (self->freq_shift && channel == 1) {
449-
self->echo_buffer_right_pos = echo_buffer_pos;
450-
} else {
451-
self->echo_buffer_pos = echo_buffer_pos;
452-
}
453466
}
454467

455468
// Finally pass our buffer and length to the calling audio function

shared-module/audiodelays/Echo.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ typedef struct {
3737
uint32_t echo_buffer_len; // bytes
3838
uint32_t max_echo_buffer_len; // bytes
3939

40-
uint32_t echo_buffer_pos; // words (<< 8 when freq_shift=True)
41-
uint32_t echo_buffer_right_pos; // words << 8
40+
uint32_t echo_buffer_left_pos; // words (<< 8 when freq_shift=True)
41+
uint32_t echo_buffer_right_pos; // words (<< 8 when freq_shift=True)
4242
uint32_t echo_buffer_rate; // words << 8
4343

4444
mp_obj_t sample;

0 commit comments

Comments
 (0)