@@ -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_left_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
104+ self -> echo_buffer_right_pos = 0 ;
106105}
107106
108107void common_hal_audiodelays_echo_deinit (audiodelays_echo_obj_t * self ) {
@@ -128,30 +127,32 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
128127 // Require that delay is at least 1 sample long
129128 f_delay_ms = MAX (f_delay_ms , self -> sample_ms );
130129
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+
131133 if (self -> freq_shift ) {
132134 // Calculate the rate of iteration over the echo buffer with 8 sub-bits
133135 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 ;
136+ // Only use half of the buffer per channel if stereo
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 ));
138-
139- // Check if our new echo is too long for our maximum buffer
140- if (new_echo_buffer_len > self -> max_echo_buffer_len ) {
141- return ;
142- } else if (new_echo_buffer_len < 0.0 ) { // or too short!
143- return ;
144- }
145-
146- // If the echo buffer is larger then our audio buffer weird things happen
147- if (new_echo_buffer_len < self -> buffer_len ) {
148- return ;
140+ uint32_t new_echo_buffer_len = (uint32_t )(self -> base .sample_rate / MICROPY_FLOAT_CONST (1000.0 ) * f_delay_ms ) * sizeof (uint16_t );
141+
142+ // Limit to valid range
143+ if (new_echo_buffer_len > max_echo_buffer_len ) {
144+ new_echo_buffer_len = max_echo_buffer_len ;
145+ } else if (new_echo_buffer_len < self -> buffer_len ) {
146+ // If the echo buffer is smaller than our audio buffer, weird things happen
147+ new_echo_buffer_len = self -> buffer_len ;
149148 }
150149
151150 self -> echo_buffer_len = new_echo_buffer_len ;
152151
153152 // Clear the now unused part of the buffer or some weird artifacts appear
154- 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+ }
155156 }
156157
157158 self -> current_delay_ms = f_delay_ms ;
@@ -178,6 +179,12 @@ bool common_hal_audiodelays_echo_get_freq_shift(audiodelays_echo_obj_t *self) {
178179}
179180
180181void common_hal_audiodelays_echo_set_freq_shift (audiodelays_echo_obj_t * self , bool freq_shift ) {
182+ // Clear the echo buffer and reset buffer position if changing freq_shift modes
183+ if (self -> freq_shift != freq_shift ) {
184+ memset (self -> echo_buffer , 0 , self -> max_echo_buffer_len );
185+ self -> echo_buffer_left_pos = 0 ;
186+ self -> echo_buffer_right_pos = 0 ;
187+ }
181188 self -> freq_shift = freq_shift ;
182189 uint32_t delay_ms = (uint32_t )synthio_block_slot_get (& self -> delay_ms );
183190 recalculate_delay (self , delay_ms );
@@ -277,15 +284,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
277284 }
278285
279286 uint32_t echo_buf_len = self -> echo_buffer_len / sizeof (uint16_t );
280-
281- // Set our echo buffer position accounting for stereo
282- uint32_t echo_buffer_pos = 0 ;
283- if (self -> freq_shift ) {
284- echo_buffer_pos = self -> echo_buffer_left_pos ;
285- if (channel == 1 ) {
286- echo_buffer_pos = self -> echo_buffer_right_pos ;
287- }
288- }
287+ uint32_t max_echo_buf_len = (self -> max_echo_buffer_len >> (self -> base .channel_count - 1 )) / sizeof (uint16_t );
289288
290289 // If we have no sample keep the echo echoing
291290 if (self -> sample == NULL ) {
@@ -309,18 +308,22 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
309308 int16_t echo , word = 0 ;
310309 uint32_t next_buffer_pos = 0 ;
311310
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 ;
314+
312315 if (self -> freq_shift ) {
313- echo = echo_buffer [echo_buffer_pos >> 8 ];
316+ echo = echo_buffer [( echo_buffer_pos >> 8 ) + echo_buffer_offset ];
314317 next_buffer_pos = echo_buffer_pos + self -> echo_buffer_rate ;
315318
316319 for (uint32_t j = echo_buffer_pos >> 8 ; j < next_buffer_pos >> 8 ; j ++ ) {
317- word = (int16_t )(echo_buffer [j % echo_buf_len ] * decay );
318- echo_buffer [j % echo_buf_len ] = word ;
320+ word = (int16_t )(echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] * decay );
321+ echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] = word ;
319322 }
320323 } else {
321- echo = echo_buffer [self -> echo_buffer_read_pos ++ ];
324+ echo = echo_buffer [echo_buffer_pos + echo_buffer_offset ];
322325 word = (int16_t )(echo * decay );
323- echo_buffer [self -> echo_buffer_write_pos ++ ] = word ;
326+ echo_buffer [echo_buffer_pos ++ + echo_buffer_offset ] = word ;
324327 }
325328
326329 word = (int16_t )(echo * mix );
@@ -339,13 +342,15 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
339342
340343 if (self -> freq_shift ) {
341344 echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8 );
345+ } else if (!self -> freq_shift && echo_buffer_pos >= echo_buf_len ) {
346+ echo_buffer_pos = 0 ;
347+ }
348+
349+ // Update buffer position
350+ if (echo_buffer_offset ) {
351+ self -> echo_buffer_right_pos = echo_buffer_pos ;
342352 } else {
343- if (self -> echo_buffer_read_pos >= echo_buf_len ) {
344- self -> echo_buffer_read_pos = 0 ;
345- }
346- if (self -> echo_buffer_write_pos >= echo_buf_len ) {
347- self -> echo_buffer_write_pos = 0 ;
348- }
353+ self -> echo_buffer_left_pos = echo_buffer_pos ;
349354 }
350355 }
351356 }
@@ -380,37 +385,42 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
380385
381386 int32_t echo , word = 0 ;
382387 uint32_t next_buffer_pos = 0 ;
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 ;
392+
383393 if (self -> freq_shift ) {
384- echo = echo_buffer [echo_buffer_pos >> 8 ];
394+ echo = echo_buffer [( echo_buffer_pos >> 8 ) + echo_buffer_offset ];
385395 next_buffer_pos = echo_buffer_pos + self -> echo_buffer_rate ;
386396 } else {
387- echo = echo_buffer [self -> echo_buffer_read_pos ++ ];
397+ echo = echo_buffer [echo_buffer_pos + echo_buffer_offset ];
388398 word = (int32_t )(echo * decay + sample_word );
389399 }
390400
391401 if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
392402 if (self -> freq_shift ) {
393403 for (uint32_t j = echo_buffer_pos >> 8 ; j < next_buffer_pos >> 8 ; j ++ ) {
394- word = (int32_t )(echo_buffer [j % echo_buf_len ] * decay + sample_word );
404+ word = (int32_t )(echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] * decay + sample_word );
395405 word = synthio_mix_down_sample (word , SYNTHIO_MIX_DOWN_SCALE (2 ));
396- echo_buffer [j % echo_buf_len ] = (int16_t )word ;
406+ echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] = (int16_t )word ;
397407 }
398408 } else {
399409 word = synthio_mix_down_sample (word , SYNTHIO_MIX_DOWN_SCALE (2 ));
400- echo_buffer [self -> echo_buffer_write_pos ++ ] = (int16_t )word ;
410+ echo_buffer [echo_buffer_pos ++ + echo_buffer_offset ] = (int16_t )word ;
401411 }
402412 } else {
403413 if (self -> freq_shift ) {
404414 for (uint32_t j = echo_buffer_pos >> 8 ; j < next_buffer_pos >> 8 ; j ++ ) {
405- word = (int32_t )(echo_buffer [j % echo_buf_len ] * decay + sample_word );
415+ word = (int32_t )(echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] * decay + sample_word );
406416 // Do not have mix_down for 8 bit so just hard cap samples into 1 byte
407417 word = MIN (MAX (word , -128 ), 127 );
408- echo_buffer [j % echo_buf_len ] = (int8_t )word ;
418+ echo_buffer [( j % echo_buf_len ) + echo_buffer_offset ] = (int8_t )word ;
409419 }
410420 } else {
411421 // Do not have mix_down for 8 bit so just hard cap samples into 1 byte
412422 word = MIN (MAX (word , -128 ), 127 );
413- echo_buffer [self -> echo_buffer_write_pos ++ ] = (int8_t )word ;
423+ echo_buffer [echo_buffer_pos ++ + echo_buffer_offset ] = (int8_t )word ;
414424 }
415425 }
416426
@@ -433,13 +443,15 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
433443
434444 if (self -> freq_shift ) {
435445 echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8 );
446+ } else if (!self -> freq_shift && echo_buffer_pos >= echo_buf_len ) {
447+ echo_buffer_pos = 0 ;
448+ }
449+
450+ // Update buffer position
451+ if (echo_buffer_offset ) {
452+ self -> echo_buffer_right_pos = echo_buffer_pos ;
436453 } else {
437- if (self -> echo_buffer_read_pos >= echo_buf_len ) {
438- self -> echo_buffer_read_pos = 0 ;
439- }
440- if (self -> echo_buffer_write_pos >= echo_buf_len ) {
441- self -> echo_buffer_write_pos = 0 ;
442- }
454+ self -> echo_buffer_left_pos = echo_buffer_pos ;
443455 }
444456 }
445457 }
@@ -451,14 +463,6 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
451463 self -> sample_remaining_buffer += (n * (self -> base .bits_per_sample / 8 ));
452464 self -> sample_buffer_length -= n ;
453465 }
454-
455- if (self -> freq_shift ) {
456- if (channel == 0 ) {
457- self -> echo_buffer_left_pos = echo_buffer_pos ;
458- } else if (channel == 1 ) {
459- self -> echo_buffer_right_pos = echo_buffer_pos ;
460- }
461- }
462466 }
463467
464468 // Finally pass our buffer and length to the calling audio function
0 commit comments