@@ -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