Skip to content

Commit 57022f9

Browse files
committed
Implemented soft clipping and continued optimization of distortion algorithms.
1 parent 0410d22 commit 57022f9

File tree

1 file changed

+67
-27
lines changed

1 file changed

+67
-27
lines changed

shared-module/audiofilters/Distortion.c

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,16 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
218218
mp_float_t post_gain = db_to_linear(synthio_block_slot_get_limited(&self->post_gain, MICROPY_FLOAT_CONST(-80.0), MICROPY_FLOAT_CONST(24.0)));
219219
mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
220220

221+
// LOFI mode bit mask
222+
uint32_t word_mask = 0xFFFFFFFF ^ ((1 << (uint32_t)MICROPY_FLOAT_C_FUN(round)(drive * MICROPY_FLOAT_CONST(14.0))) - 1);
223+
224+
// Modify drive value depending on mode
225+
if (self->mode == DISTORTION_MODE_CLIP) {
226+
drive = MICROPY_FLOAT_CONST(1.0001) - drive;
227+
} else if (self->mode == DISTORTION_MODE_WAVESHAPE) {
228+
drive = MICROPY_FLOAT_CONST(2.0) * drive / (MICROPY_FLOAT_CONST(1.0001) - drive);
229+
}
230+
221231
// Switch our buffers to the other buffer
222232
self->last_buf_idx = !self->last_buf_idx;
223233

@@ -267,7 +277,7 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
267277
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples
268278
int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples
269279

270-
if (mix <= 0.01) { // if mix is zero pure sample only
280+
if (mix <= MICROPY_FLOAT_CONST(0.01)) { // if mix is zero pure sample only
271281
for (uint32_t i = 0; i < n; i++) {
272282
if (MP_LIKELY(self->bits_per_sample == 16)) {
273283
word_buffer[i] = sample_src[i];
@@ -276,9 +286,6 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
276286
}
277287
}
278288
} else {
279-
280-
uint32_t word_mask = 0xFFFFFFFF ^ ((1 << (uint32_t)roundf(drive * 14.0)) - 1); // LOFI mode bit mask
281-
282289
for (uint32_t i = 0; i < n; i++) {
283290
int32_t sample_word = 0;
284291
if (MP_LIKELY(self->bits_per_sample == 16)) {
@@ -292,37 +299,70 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
292299
}
293300
}
294301

302+
// Apply pre-gain
295303
int32_t word = sample_word * pre_gain;
296-
switch (self->mode) {
297-
case DISTORTION_MODE_CLIP: {
298-
mp_float_t word_sign = word < 0 ? MICROPY_FLOAT_CONST(-1.0) : MICROPY_FLOAT_CONST(1.0);
299-
word = MICROPY_FLOAT_C_FUN(pow)(MICROPY_FLOAT_C_FUN(fabs)(word / MICROPY_FLOAT_CONST(32768.0)), MICROPY_FLOAT_CONST(1.0001) - drive) * word_sign * MICROPY_FLOAT_CONST(32767.0);
300-
word = MIN(MAX(word, -32767), 32768); // Hard clip
301-
} break;
302-
case DISTORTION_MODE_LOFI: {
303-
word = word & word_mask;
304-
} break;
305-
case DISTORTION_MODE_OVERDRIVE: {
306-
mp_float_t x = word / MICROPY_FLOAT_CONST(32768.0) * MICROPY_FLOAT_CONST(0.686306);
307-
mp_float_t z = MICROPY_FLOAT_CONST(1.0) + MICROPY_FLOAT_C_FUN(exp)(MICROPY_FLOAT_C_FUN(sqrt)(MICROPY_FLOAT_C_FUN(fabs)(x)) * MICROPY_FLOAT_CONST(-0.75));
308-
mp_float_t exp_x = MICROPY_FLOAT_C_FUN(exp)(x);
309-
word = (exp_x - MICROPY_FLOAT_C_FUN(exp)(-x * z)) / (exp_x + MICROPY_FLOAT_C_FUN(exp)(-x)) * MICROPY_FLOAT_CONST(32767.0);
310-
} break;
311-
case DISTORTION_MODE_WAVESHAPE: {
312-
mp_float_t x = word / MICROPY_FLOAT_CONST(32768.0);
313-
mp_float_t k = MICROPY_FLOAT_CONST(2.0) * drive / (MICROPY_FLOAT_CONST(1.00001) - drive);
314-
word = (MICROPY_FLOAT_CONST(1.0) + k) * x / (MICROPY_FLOAT_CONST(1.0) + k * MICROPY_FLOAT_C_FUN(fabs)(x)) * MICROPY_FLOAT_CONST(32767.0);
315-
} break;
304+
305+
// Apply bit mask before converting to float
306+
if (self->mode == DISTORTION_MODE_LOFI) {
307+
word = word & word_mask;
308+
}
309+
310+
if (self->mode != DISTORTION_MODE_LOFI || self->soft_clip) {
311+
// Convert sample to float
312+
mp_float_t wordf = word / MICROPY_FLOAT_CONST(32768.0);
313+
314+
switch (self->mode) {
315+
case DISTORTION_MODE_CLIP: {
316+
wordf = MICROPY_FLOAT_C_FUN(pow)(MICROPY_FLOAT_C_FUN(fabs)(wordf), drive);
317+
if (word < 0) {
318+
wordf *= MICROPY_FLOAT_CONST(-1.0);
319+
}
320+
} break;
321+
case DISTORTION_MODE_LOFI:
322+
break;
323+
case DISTORTION_MODE_OVERDRIVE: {
324+
wordf *= MICROPY_FLOAT_CONST(0.686306);
325+
mp_float_t z = MICROPY_FLOAT_CONST(1.0) + MICROPY_FLOAT_C_FUN(exp)(MICROPY_FLOAT_C_FUN(sqrt)(MICROPY_FLOAT_C_FUN(fabs)(wordf)) * MICROPY_FLOAT_CONST(-0.75));
326+
mp_float_t word_exp = MICROPY_FLOAT_C_FUN(exp)(wordf);
327+
wordf *= MICROPY_FLOAT_CONST(-1.0);
328+
wordf = (word_exp - MICROPY_FLOAT_C_FUN(exp)(wordf * z)) / (word_exp + MICROPY_FLOAT_C_FUN(exp)(wordf));
329+
} break;
330+
case DISTORTION_MODE_WAVESHAPE: {
331+
wordf = (MICROPY_FLOAT_CONST(1.0) + drive) * wordf / (MICROPY_FLOAT_CONST(1.0) + drive * MICROPY_FLOAT_C_FUN(fabs)(wordf));
332+
} break;
333+
}
334+
335+
// Apply post-gain
336+
wordf = wordf * post_gain;
337+
338+
// Soft clip
339+
if (self->soft_clip) {
340+
if (wordf > 0) {
341+
wordf = MICROPY_FLOAT_CONST(1.0) - MICROPY_FLOAT_C_FUN(exp)(-wordf);
342+
} else {
343+
wordf = MICROPY_FLOAT_CONST(-1.0) + MICROPY_FLOAT_C_FUN(exp)(wordf);
344+
}
345+
}
346+
347+
// Convert sample back to signed integer
348+
word = wordf * MICROPY_FLOAT_CONST(32767.0);
349+
} else {
350+
// Apply post-gain
351+
word = word * post_gain;
352+
}
353+
354+
// Hard clip
355+
if (!self->soft_clip) {
356+
word = MIN(MAX(word, -32767), 32768);
316357
}
317-
word = word * post_gain;
318358

319359
if (MP_LIKELY(self->bits_per_sample == 16)) {
320-
word_buffer[i] = (sample_word * (1.0 - mix)) + (word * mix);
360+
word_buffer[i] = (sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix);
321361
if (!self->samples_signed) {
322362
word_buffer[i] ^= 0x8000;
323363
}
324364
} else {
325-
int8_t mixed = (sample_word * (1.0 - mix)) + (word * mix);
365+
int8_t mixed = (sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix);
326366
if (self->samples_signed) {
327367
hword_buffer[i] = mixed;
328368
} else {

0 commit comments

Comments
 (0)