@@ -98,11 +98,10 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
98
98
99
99
// read is where we read previous echo from delay_ms ago to play back now
100
100
// 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 ;
103
102
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 ;
106
105
}
107
106
108
107
void 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) {
128
127
// Require that delay is at least 1 sample long
129
128
f_delay_ms = MAX (f_delay_ms , self -> sample_ms );
130
129
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
+
131
133
if (self -> freq_shift ) {
132
134
// Calculate the rate of iteration over the echo buffer with 8 sub-bits
133
135
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 ;
135
138
} else {
136
139
// 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 ;
149
148
}
150
149
151
150
self -> echo_buffer_len = new_echo_buffer_len ;
152
151
153
152
// 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
+ }
155
156
}
156
157
157
158
self -> current_delay_ms = f_delay_ms ;
@@ -178,6 +179,12 @@ bool common_hal_audiodelays_echo_get_freq_shift(audiodelays_echo_obj_t *self) {
178
179
}
179
180
180
181
void 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
+ }
181
188
self -> freq_shift = freq_shift ;
182
189
uint32_t delay_ms = (uint32_t )synthio_block_slot_get (& self -> delay_ms );
183
190
recalculate_delay (self , delay_ms );
@@ -277,15 +284,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
277
284
}
278
285
279
286
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 );
289
288
290
289
// If we have no sample keep the echo echoing
291
290
if (self -> sample == NULL ) {
@@ -309,18 +308,22 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
309
308
int16_t echo , word = 0 ;
310
309
uint32_t next_buffer_pos = 0 ;
311
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 ;
314
+
312
315
if (self -> freq_shift ) {
313
- echo = echo_buffer [echo_buffer_pos >> 8 ];
316
+ echo = echo_buffer [( echo_buffer_pos >> 8 ) + echo_buffer_offset ];
314
317
next_buffer_pos = echo_buffer_pos + self -> echo_buffer_rate ;
315
318
316
319
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 ;
319
322
}
320
323
} else {
321
- echo = echo_buffer [self -> echo_buffer_read_pos ++ ];
324
+ echo = echo_buffer [echo_buffer_pos + echo_buffer_offset ];
322
325
word = (int16_t )(echo * decay );
323
- echo_buffer [self -> echo_buffer_write_pos ++ ] = word ;
326
+ echo_buffer [echo_buffer_pos ++ + echo_buffer_offset ] = word ;
324
327
}
325
328
326
329
word = (int16_t )(echo * mix );
@@ -339,13 +342,15 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
339
342
340
343
if (self -> freq_shift ) {
341
344
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 ;
342
352
} 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 ;
349
354
}
350
355
}
351
356
}
@@ -380,37 +385,42 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
380
385
381
386
int32_t echo , word = 0 ;
382
387
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
+
383
393
if (self -> freq_shift ) {
384
- echo = echo_buffer [echo_buffer_pos >> 8 ];
394
+ echo = echo_buffer [( echo_buffer_pos >> 8 ) + echo_buffer_offset ];
385
395
next_buffer_pos = echo_buffer_pos + self -> echo_buffer_rate ;
386
396
} else {
387
- echo = echo_buffer [self -> echo_buffer_read_pos ++ ];
397
+ echo = echo_buffer [echo_buffer_pos + echo_buffer_offset ];
388
398
word = (int32_t )(echo * decay + sample_word );
389
399
}
390
400
391
401
if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
392
402
if (self -> freq_shift ) {
393
403
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 );
395
405
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 ;
397
407
}
398
408
} else {
399
409
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 ;
401
411
}
402
412
} else {
403
413
if (self -> freq_shift ) {
404
414
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 );
406
416
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
407
417
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 ;
409
419
}
410
420
} else {
411
421
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
412
422
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 ;
414
424
}
415
425
}
416
426
@@ -433,13 +443,15 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
433
443
434
444
if (self -> freq_shift ) {
435
445
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 ;
436
453
} 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 ;
443
455
}
444
456
}
445
457
}
@@ -451,14 +463,6 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
451
463
self -> sample_remaining_buffer += (n * (self -> base .bits_per_sample / 8 ));
452
464
self -> sample_buffer_length -= n ;
453
465
}
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
- }
462
466
}
463
467
464
468
// Finally pass our buffer and length to the calling audio function
0 commit comments