Skip to content

Commit 00a149a

Browse files
committed
More comments and cleanup
1 parent 70c0bf9 commit 00a149a

File tree

1 file changed

+38
-28
lines changed
  • shared-module/audiodelays

1 file changed

+38
-28
lines changed

shared-module/audiodelays/Echo.c

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
6161
synthio_block_assign_slot(decay, &self->decay, MP_QSTR_decay);
6262

6363
if (delay_ms == MP_OBJ_NULL) {
64-
delay_ms = mp_obj_new_float(0.05);
64+
delay_ms = mp_obj_new_float(500.0);
6565
}
6666
synthio_block_assign_slot(delay_ms, &self->delay_ms, MP_QSTR_delay_ms);
6767

@@ -74,9 +74,9 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
7474
// A maximum length buffer was created and then the current echo length can be dynamically changes
7575
// without having to reallocate a large chunk of memory.
7676

77-
// Allocate the echo buffer for the max possible delay
77+
// Allocate the echo buffer for the max possible delay, echo is always 16-bit
7878
self->max_delay_ms = max_delay_ms;
79-
self->max_echo_buffer_len = self->sample_rate / 1000.0f * max_delay_ms * (self->channel_count * 2);// (self->bits_per_sample / 8)); // bytes
79+
self->max_echo_buffer_len = self->sample_rate / 1000.0f * max_delay_ms * (self->channel_count * sizeof(uint16_t)); // bytes
8080
self->echo_buffer = m_malloc(self->max_echo_buffer_len);
8181
if (self->echo_buffer == NULL) {
8282
common_hal_audiodelays_echo_deinit(self);
@@ -86,11 +86,11 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
8686

8787
// calculate current echo buffer size we use for the given delay
8888
mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms);
89-
self->echo_buffer_len = self->sample_rate / 1000.0f * f_delay_ms * (self->channel_count * 2);// (self->bits_per_sample / 8));
89+
self->echo_buffer_len = self->sample_rate / 1000.0f * f_delay_ms * (self->channel_count * sizeof(uint16_t));
9090

9191
// read is where we store the incoming sample + previous echo
9292
// write is what we send to the outgoing buffer
93-
self->echo_buffer_read_pos = self->buffer_len / 2;// (self->bits_per_sample / 8);
93+
self->echo_buffer_read_pos = self->buffer_len / sizeof(uint16_t);
9494
self->echo_buffer_write_pos = 0;
9595
}
9696

@@ -164,6 +164,9 @@ void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self,
164164
bool single_channel_output,
165165
uint8_t channel) {
166166

167+
memset(self->buffer[0], 0, self->buffer_len);
168+
memset(self->buffer[1], 0, self->buffer_len);
169+
memset(self->echo_buffer, 0, self->max_echo_buffer_len);
167170
}
168171

169172
bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self) {
@@ -201,6 +204,7 @@ void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sam
201204

202205
// Track remaining sample length in terms of bytes per sample
203206
self->sample_buffer_length /= (self->bits_per_sample / 8);
207+
// Store if we have more data in the sample to retrieve
204208
self->more_data = result == GET_BUFFER_MORE_DATA;
205209

206210
return;
@@ -213,10 +217,10 @@ void common_hal_audiodelays_echo_stop(audiodelays_echo_obj_t *self) {
213217
return;
214218
}
215219

216-
#define RANGE_LOW (-28000)
217-
#define RANGE_HIGH (28000)
218-
#define RANGE_SHIFT (16)
219-
#define RANGE_SCALE (0xfffffff / (32768 * 4 - RANGE_HIGH))
220+
#define RANGE_LOW_16 (-28000)
221+
#define RANGE_HIGH_16 (28000)
222+
#define RANGE_SHIFT_16 (16)
223+
#define RANGE_SCALE_16 (0xfffffff / (32768 * 2 - RANGE_HIGH_16)) // 2 for echo+sample
220224

221225
// dynamic range compression via a downward compressor with hard knee
222226
//
@@ -231,10 +235,10 @@ void common_hal_audiodelays_echo_stop(audiodelays_echo_obj_t *self) {
231235
// https://en.wikipedia.org/wiki/Dynamic_range_compression
232236
static
233237
int16_t mix_down_sample(int32_t sample) {
234-
if (sample < RANGE_LOW) {
235-
sample = (((sample - RANGE_LOW) * RANGE_SCALE) >> RANGE_SHIFT) + RANGE_LOW;
236-
} else if (sample > RANGE_HIGH) {
237-
sample = (((sample - RANGE_HIGH) * RANGE_SCALE) >> RANGE_SHIFT) + RANGE_HIGH;
238+
if (sample < RANGE_LOW_16) {
239+
sample = (((sample - RANGE_LOW_16) * RANGE_SCALE_16) >> RANGE_SHIFT_16) + RANGE_LOW_16;
240+
} else if (sample > RANGE_HIGH_16) {
241+
sample = (((sample - RANGE_HIGH_16) * RANGE_SCALE_16) >> RANGE_SHIFT_16) + RANGE_HIGH_16;
238242
}
239243
return sample;
240244
}
@@ -249,20 +253,18 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
249253
// Switch our buffers to the other buffer
250254
self->last_buf_idx = !self->last_buf_idx;
251255

252-
// If we are using 16 bit samples we need a 16 bit pointer
256+
// If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer
253257
int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx];
254258
int8_t *hword_buffer = self->buffer[self->last_buf_idx];
255259
uint32_t length = self->buffer_len / (self->bits_per_sample / 8);
256260

257261
// The echo buffer is always stored as a 16-bit value internally
258262
int16_t *echo_buffer = (int16_t *)self->echo_buffer;
259-
uint32_t echo_buf_len = self->echo_buffer_len / 2;// (self->bits_per_sample / 8);
260-
263+
uint32_t echo_buf_len = self->echo_buffer_len / sizeof(uint16_t);
261264

262265
// Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample
263266
while (length != 0) {
264-
265-
// Check if there is no more sample to play
267+
// Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample
266268
if (self->sample_buffer_length == 0) {
267269
if (!self->more_data) { // The sample has indicated it has no more data to play
268270
if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start
@@ -286,10 +288,15 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
286288
if (self->samples_signed) {
287289
memset(word_buffer, 0, length * (self->bits_per_sample / 8));
288290
} else {
289-
memset(hword_buffer, 128, length * (self->bits_per_sample / 8));
291+
// For unsigned samples set to the middle which is "quiet"
292+
if (MP_LIKELY(self->bits_per_sample == 16)) {
293+
memset(word_buffer, 32768, length * (self->bits_per_sample / 8));
294+
} else {
295+
memset(hword_buffer, 128, length * (self->bits_per_sample / 8));
296+
}
290297
}
291298
} else {
292-
// Since we have no sample we can just iterate over the our entire remaining buffer
299+
// Since we have no sample we can just iterate over the our entire remaining buffer and finish
293300
for (uint32_t i = 0; i < length; i++) {
294301
int16_t echo = echo_buffer[self->echo_buffer_read_pos++] * decay;
295302
echo_buffer[self->echo_buffer_write_pos++] = echo;
@@ -319,12 +326,11 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
319326
length = 0;
320327
} else {
321328
// we have a sample to play and echo
322-
323329
// Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining
324330
uint32_t n = MIN(self->sample_buffer_length, length);
325331

326-
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer;
327-
int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer;
332+
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples
333+
int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples
328334

329335
if (mix <= 0.01) { // if mix is zero pure sample only
330336
for (uint32_t i = 0; i < n; i++) {
@@ -343,20 +349,19 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
343349
if (self->samples_signed) {
344350
sample_word = sample_hsrc[i];
345351
} else {
346-
// uint8_t s1 = sample_hsrc[i];
347-
// int8_t s2 = s1^0x80;
348-
// sample_word = s2;
349-
352+
// Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed
350353
sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80);
351354
}
352355
}
353356

354357
int32_t echo = echo_buffer[self->echo_buffer_read_pos++] * decay;
355358
int32_t word = echo + sample_word;
359+
356360
if (MP_LIKELY(self->bits_per_sample == 16)) {
357361
word = mix_down_sample(word);
358362
echo_buffer[self->echo_buffer_write_pos++] = (int16_t)word;
359363
} else {
364+
// Do not have mix_down for 8 bit so just hard cap samples into 1 byte
360365
if (word > 127) {
361366
word = 127;
362367
} else if (word < -128) {
@@ -372,7 +377,6 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
372377
}
373378
} else {
374379
int8_t mixed = (sample_word * (1.0 - mix)) + (word * mix);
375-
;
376380
if (self->samples_signed) {
377381
hword_buffer[i] = mixed;
378382
} else {
@@ -389,6 +393,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
389393
}
390394
}
391395

396+
// Update the remaining length and the buffer positions based on how much we wrote into our buffer
392397
length -= n;
393398
word_buffer += n;
394399
hword_buffer += n;
@@ -397,14 +402,19 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
397402
}
398403
}
399404

405+
// Finally pass our buffer and length to the calling audio function
400406
*buffer = (uint8_t *)self->buffer[self->last_buf_idx];
401407
*buffer_length = self->buffer_len;
408+
409+
// Echo always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h)
402410
return GET_BUFFER_MORE_DATA;
403411
}
404412

405413
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self, bool single_channel_output,
406414
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
407415

416+
// Return information about the effect's buffer (not the sample's)
417+
// These are used by calling audio objects to determine how to handle the effect's buffer
408418
*single_buffer = false;
409419
*samples_signed = self->samples_signed;
410420
*max_buffer_length = self->buffer_len;

0 commit comments

Comments
 (0)