Unify echo buffer channel splitting.
This commit is contained in:
parent
feee74a5e2
commit
7d0e72e5ca
2 changed files with 45 additions and 32 deletions
|
|
@ -98,9 +98,9 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
|
|||
|
||||
// read is where we read previous echo from delay_ms ago to play back now
|
||||
// write is where the store the latest playing sample to echo back later
|
||||
self->echo_buffer_pos = 0;
|
||||
self->echo_buffer_left_pos = 0;
|
||||
|
||||
// use a separate buffer position for the right channel when using freq_shift
|
||||
// use a separate buffer position for the right channel
|
||||
self->echo_buffer_right_pos = 0;
|
||||
}
|
||||
|
||||
|
|
@ -127,18 +127,21 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
|
|||
// Require that delay is at least 1 sample long
|
||||
f_delay_ms = MAX(f_delay_ms, self->sample_ms);
|
||||
|
||||
// Calculate the maximum buffer size per channel in bytes
|
||||
uint32_t max_echo_buffer_len = self->max_echo_buffer_len >> (self->base.channel_count - 1);
|
||||
|
||||
if (self->freq_shift) {
|
||||
// Calculate the rate of iteration over the echo buffer with 8 sub-bits
|
||||
self->echo_buffer_rate = (uint32_t)MAX(self->max_delay_ms / f_delay_ms * MICROPY_FLOAT_CONST(256.0), MICROPY_FLOAT_CONST(1.0));
|
||||
// Only use half of the buffer per channel if stereo
|
||||
self->echo_buffer_len = self->max_echo_buffer_len >> (self->base.channel_count - 1);
|
||||
self->echo_buffer_len = max_echo_buffer_len;
|
||||
} else {
|
||||
// Calculate the current echo buffer length in bytes
|
||||
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));
|
||||
uint32_t new_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * sizeof(uint16_t);
|
||||
|
||||
// Limit to valid range
|
||||
if (new_echo_buffer_len > self->max_echo_buffer_len) {
|
||||
new_echo_buffer_len = self->max_echo_buffer_len;
|
||||
if (new_echo_buffer_len > max_echo_buffer_len) {
|
||||
new_echo_buffer_len = max_echo_buffer_len;
|
||||
} else if (new_echo_buffer_len < self->buffer_len) {
|
||||
// If the echo buffer is smaller than our audio buffer, weird things happen
|
||||
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) {
|
|||
self->echo_buffer_len = new_echo_buffer_len;
|
||||
|
||||
// Clear the now unused part of the buffer or some weird artifacts appear
|
||||
memset(self->echo_buffer + self->echo_buffer_len, 0, self->max_echo_buffer_len - self->echo_buffer_len);
|
||||
for (uint32_t i = 0; i < self->base.channel_count; i++) {
|
||||
memset(self->echo_buffer + (i * max_echo_buffer_len) + self->echo_buffer_len, 0, max_echo_buffer_len - self->echo_buffer_len);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
|||
// Clear the echo buffer and reset buffer position if changing freq_shift modes
|
||||
if (self->freq_shift != freq_shift) {
|
||||
memset(self->echo_buffer, 0, self->max_echo_buffer_len);
|
||||
self->echo_buffer_pos = 0;
|
||||
self->echo_buffer_left_pos = 0;
|
||||
self->echo_buffer_right_pos = 0;
|
||||
}
|
||||
self->freq_shift = freq_shift;
|
||||
|
|
@ -279,12 +284,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
}
|
||||
|
||||
uint32_t echo_buf_len = self->echo_buffer_len / sizeof(uint16_t);
|
||||
|
||||
// Set our echo buffer position accounting for stereo
|
||||
uint32_t echo_buffer_pos = self->echo_buffer_pos;
|
||||
if (self->freq_shift && channel == 1) {
|
||||
echo_buffer_pos = self->echo_buffer_right_pos;
|
||||
}
|
||||
uint32_t max_echo_buf_len = (self->max_echo_buffer_len >> (self->base.channel_count - 1)) / sizeof(uint16_t);
|
||||
|
||||
// If we have no sample keep the echo echoing
|
||||
if (self->sample == NULL) {
|
||||
|
|
@ -307,7 +307,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
for (uint32_t i = 0; i < length; i++) {
|
||||
int16_t echo, word = 0;
|
||||
uint32_t next_buffer_pos = 0;
|
||||
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)));
|
||||
|
||||
// Get our echo buffer position and offset depending on current channel
|
||||
uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1));
|
||||
uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos;
|
||||
|
||||
if (self->freq_shift) {
|
||||
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 *
|
|||
echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = word;
|
||||
}
|
||||
} else {
|
||||
echo = echo_buffer[echo_buffer_pos];
|
||||
echo = echo_buffer[echo_buffer_pos + echo_buffer_offset];
|
||||
word = (int16_t)(echo * decay);
|
||||
echo_buffer[echo_buffer_pos++] = word;
|
||||
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = word;
|
||||
}
|
||||
|
||||
word = (int16_t)(echo * mix);
|
||||
|
|
@ -337,11 +340,18 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
}
|
||||
}
|
||||
|
||||
if (self->freq_shift && (self->base.channel_count == 1 || single_channel_output || (!single_channel_output && (i % self->base.channel_count) == 1))) {
|
||||
if (self->freq_shift) {
|
||||
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
|
||||
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
|
||||
echo_buffer_pos = 0;
|
||||
}
|
||||
|
||||
// Update buffer position
|
||||
if (echo_buffer_offset) {
|
||||
self->echo_buffer_right_pos = echo_buffer_pos;
|
||||
} else {
|
||||
self->echo_buffer_left_pos = echo_buffer_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -375,13 +385,16 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
|
||||
int32_t echo, word = 0;
|
||||
uint32_t next_buffer_pos = 0;
|
||||
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)));
|
||||
|
||||
// Get our echo buffer position and offset depending on current channel
|
||||
uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1));
|
||||
uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos;
|
||||
|
||||
if (self->freq_shift) {
|
||||
echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset];
|
||||
next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate;
|
||||
} else {
|
||||
echo = echo_buffer[echo_buffer_pos];
|
||||
echo = echo_buffer[echo_buffer_pos + echo_buffer_offset];
|
||||
word = (int32_t)(echo * decay + sample_word);
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +407,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
}
|
||||
} else {
|
||||
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
|
||||
echo_buffer[echo_buffer_pos++] = (int16_t)word;
|
||||
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int16_t)word;
|
||||
}
|
||||
} else {
|
||||
if (self->freq_shift) {
|
||||
|
|
@ -407,7 +420,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
} else {
|
||||
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
|
||||
word = MIN(MAX(word, -128), 127);
|
||||
echo_buffer[echo_buffer_pos++] = (int8_t)word;
|
||||
echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int8_t)word;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -428,11 +441,18 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
}
|
||||
}
|
||||
|
||||
if (self->freq_shift && (self->base.channel_count == 1 || single_channel_output || (!single_channel_output && (i % self->base.channel_count) == 1))) {
|
||||
if (self->freq_shift) {
|
||||
echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8);
|
||||
} else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) {
|
||||
echo_buffer_pos = 0;
|
||||
}
|
||||
|
||||
// Update buffer position
|
||||
if (echo_buffer_offset) {
|
||||
self->echo_buffer_right_pos = echo_buffer_pos;
|
||||
} else {
|
||||
self->echo_buffer_left_pos = echo_buffer_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -443,13 +463,6 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8));
|
||||
self->sample_buffer_length -= n;
|
||||
}
|
||||
|
||||
// Update buffer position
|
||||
if (self->freq_shift && channel == 1) {
|
||||
self->echo_buffer_right_pos = echo_buffer_pos;
|
||||
} else {
|
||||
self->echo_buffer_pos = echo_buffer_pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally pass our buffer and length to the calling audio function
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ typedef struct {
|
|||
uint32_t echo_buffer_len; // bytes
|
||||
uint32_t max_echo_buffer_len; // bytes
|
||||
|
||||
uint32_t echo_buffer_pos; // words (<< 8 when freq_shift=True)
|
||||
uint32_t echo_buffer_right_pos; // words << 8
|
||||
uint32_t echo_buffer_left_pos; // words (<< 8 when freq_shift=True)
|
||||
uint32_t echo_buffer_right_pos; // words (<< 8 when freq_shift=True)
|
||||
uint32_t echo_buffer_rate; // words << 8
|
||||
|
||||
mp_obj_t sample;
|
||||
|
|
|
|||
Loading…
Reference in a new issue