Skip to content

Commit 57391fa

Browse files
committed
Unify echo_buffer_pos regardless of freq_shift, remove redundant echo_buffer_write_pos, and split buffer for stereo output when freq_shift=True.
1 parent 47c9fc1 commit 57391fa

File tree

2 files changed

+43
-51
lines changed

2 files changed

+43
-51
lines changed

shared-module/audiodelays/Echo.c

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,10 @@ 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_read_pos = self->buffer_len / sizeof(uint16_t);
102-
self->echo_buffer_write_pos = 0;
101+
self->echo_buffer_pos = 0;
103102

104-
// where we read the previous echo from delay_ms ago to play back now (for freq shift)
105-
self->echo_buffer_left_pos = self->echo_buffer_right_pos = 0;
103+
// use a separate buffer position for the right channel when using freq_shift
104+
self->echo_buffer_right_pos = 0;
106105
}
107106

108107
void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self) {
@@ -131,7 +130,8 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
131130
if (self->freq_shift) {
132131
// Calculate the rate of iteration over the echo buffer with 8 sub-bits
133132
self->echo_buffer_rate = (uint32_t)MAX(self->max_delay_ms / f_delay_ms * MICROPY_FLOAT_CONST(256.0), MICROPY_FLOAT_CONST(1.0));
134-
self->echo_buffer_len = self->max_echo_buffer_len;
133+
// 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);
135135
} else {
136136
// Calculate the current echo buffer length in bytes
137137
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));
@@ -174,6 +174,12 @@ bool common_hal_audiodelays_echo_get_freq_shift(audiodelays_echo_obj_t *self) {
174174
}
175175

176176
void common_hal_audiodelays_echo_set_freq_shift(audiodelays_echo_obj_t *self, bool freq_shift) {
177+
// Clear the echo buffer and reset buffer position if changing freq_shift modes
178+
if (self->freq_shift != freq_shift) {
179+
memset(self->echo_buffer, 0, self->max_echo_buffer_len);
180+
self->echo_buffer_pos = 0;
181+
self->echo_buffer_right_pos = 0;
182+
}
177183
self->freq_shift = freq_shift;
178184
uint32_t delay_ms = (uint32_t)synthio_block_slot_get(&self->delay_ms);
179185
recalculate_delay(self, delay_ms);
@@ -275,12 +281,9 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
275281
uint32_t echo_buf_len = self->echo_buffer_len / sizeof(uint16_t);
276282

277283
// Set our echo buffer position accounting for stereo
278-
uint32_t echo_buffer_pos = 0;
279-
if (self->freq_shift) {
280-
echo_buffer_pos = self->echo_buffer_left_pos;
281-
if (channel == 1) {
282-
echo_buffer_pos = self->echo_buffer_right_pos;
283-
}
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;
284287
}
285288

286289
// If we have no sample keep the echo echoing
@@ -304,19 +307,20 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
304307
for (uint32_t i = 0; i < length; i++) {
305308
int16_t echo, word = 0;
306309
uint32_t next_buffer_pos = 0;
310+
uint32_t echo_buffer_offset = echo_buf_len * (self->freq_shift && (channel == 1 || (i % self->base.channel_count) == 1));
307311

308312
if (self->freq_shift) {
309-
echo = echo_buffer[echo_buffer_pos >> 8];
313+
echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset];
310314
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
311315

312316
for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) {
313-
word = (int16_t)(echo_buffer[j % echo_buf_len] * decay);
314-
echo_buffer[j % echo_buf_len] = word;
317+
word = (int16_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay);
318+
echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = word;
315319
}
316320
} else {
317-
echo = echo_buffer[self->echo_buffer_read_pos++];
321+
echo = echo_buffer[echo_buffer_pos];
318322
word = (int16_t)(echo * decay);
319-
echo_buffer[self->echo_buffer_write_pos++] = word;
323+
echo_buffer[echo_buffer_pos++] = word;
320324
}
321325

322326
word = (int16_t)(echo * mix);
@@ -333,15 +337,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
333337
}
334338
}
335339

336-
if (self->freq_shift) {
340+
if (self->freq_shift && (single_channel_output || echo_buffer_offset)) {
337341
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
338-
} else {
339-
if (self->echo_buffer_read_pos >= echo_buf_len) {
340-
self->echo_buffer_read_pos = 0;
341-
}
342-
if (self->echo_buffer_write_pos >= echo_buf_len) {
343-
self->echo_buffer_write_pos = 0;
344-
}
342+
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
343+
echo_buffer_pos = 0;
345344
}
346345
}
347346
}
@@ -376,37 +375,39 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
376375

377376
int32_t echo, word = 0;
378377
uint32_t next_buffer_pos = 0;
378+
uint32_t echo_buffer_offset = echo_buf_len * (self->freq_shift && (channel == 1 || (i % self->base.channel_count) == 1));
379+
379380
if (self->freq_shift) {
380-
echo = echo_buffer[echo_buffer_pos >> 8];
381+
echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset];
381382
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
382383
} else {
383-
echo = echo_buffer[self->echo_buffer_read_pos++];
384+
echo = echo_buffer[echo_buffer_pos];
384385
word = (int32_t)(echo * decay + sample_word);
385386
}
386387

387388
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
388389
if (self->freq_shift) {
389390
for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) {
390-
word = (int32_t)(echo_buffer[j % echo_buf_len] * decay + sample_word);
391+
word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word);
391392
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
392-
echo_buffer[j % echo_buf_len] = (int16_t)word;
393+
echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int16_t)word;
393394
}
394395
} else {
395396
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
396-
echo_buffer[self->echo_buffer_write_pos++] = (int16_t)word;
397+
echo_buffer[echo_buffer_pos++] = (int16_t)word;
397398
}
398399
} else {
399400
if (self->freq_shift) {
400401
for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) {
401-
word = (int32_t)(echo_buffer[j % echo_buf_len] * decay + sample_word);
402+
word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word);
402403
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
403404
word = MIN(MAX(word, -128), 127);
404-
echo_buffer[j % echo_buf_len] = (int8_t)word;
405+
echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int8_t)word;
405406
}
406407
} else {
407408
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
408409
word = MIN(MAX(word, -128), 127);
409-
echo_buffer[self->echo_buffer_write_pos++] = (int8_t)word;
410+
echo_buffer[echo_buffer_pos++] = (int8_t)word;
410411
}
411412
}
412413

@@ -427,15 +428,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
427428
}
428429
}
429430

430-
if (self->freq_shift) {
431+
if (self->freq_shift && (single_channel_output || echo_buffer_offset)) {
431432
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
432-
} else {
433-
if (self->echo_buffer_read_pos >= echo_buf_len) {
434-
self->echo_buffer_read_pos = 0;
435-
}
436-
if (self->echo_buffer_write_pos >= echo_buf_len) {
437-
self->echo_buffer_write_pos = 0;
438-
}
433+
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
434+
echo_buffer_pos = 0;
439435
}
440436
}
441437
}
@@ -448,12 +444,11 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
448444
self->sample_buffer_length -= n;
449445
}
450446

451-
if (self->freq_shift) {
452-
if (channel == 0) {
453-
self->echo_buffer_left_pos = echo_buffer_pos;
454-
} else if (channel == 1) {
455-
self->echo_buffer_right_pos = echo_buffer_pos;
456-
}
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;
457452
}
458453
}
459454

shared-module/audiodelays/Echo.h

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

40-
uint32_t echo_buffer_read_pos; // words
41-
uint32_t echo_buffer_write_pos; // words
42-
43-
uint32_t echo_buffer_rate; // words << 8
44-
uint32_t echo_buffer_left_pos; // words << 8
40+
uint32_t echo_buffer_pos; // words (<< 8 when freq_shift=True)
4541
uint32_t echo_buffer_right_pos; // words << 8
42+
uint32_t echo_buffer_rate; // words << 8
4643

4744
mp_obj_t sample;
4845
} audiodelays_echo_obj_t;

0 commit comments

Comments
 (0)