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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy