diff --git a/shared-module/audiodelays/Chorus.c b/shared-module/audiodelays/Chorus.c index 7033df0e272..ccd33975948 100644 --- a/shared-module/audiodelays/Chorus.c +++ b/shared-module/audiodelays/Chorus.c @@ -248,6 +248,7 @@ audioio_get_buffer_result_t audiodelays_chorus_get_buffer(audiodelays_chorus_obj int32_t voices = (int32_t)MAX(synthio_block_slot_get(&self->voices), 1.0); int32_t mix_down_scale = SYNTHIO_MIX_DOWN_SCALE(voices); mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int32_t mix_scaled = (int32_t)(mix * MICROPY_FLOAT_CONST(32768.0)); mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); if (MICROPY_FLOAT_C_FUN(fabs)(self->current_delay_ms - f_delay_ms) >= self->sample_ms) { @@ -311,7 +312,7 @@ audioio_get_buffer_result_t audiodelays_chorus_get_buffer(audiodelays_chorus_obj } // Add original sample + effect - word = sample_word + (int32_t)(word * mix); + word = sample_word + ((word * mix_scaled) >> 15); word = synthio_mix_down_sample(word, 2); if (MP_LIKELY(self->base.bits_per_sample == 16)) { diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c index 675c7cb5ebc..1e5d2ec0944 100644 --- a/shared-module/audiodelays/Echo.c +++ b/shared-module/audiodelays/Echo.c @@ -298,6 +298,11 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t * mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); mp_float_t decay = synthio_block_slot_get_limited(&self->decay, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int32_t decay_scaled = (int32_t)(decay * MICROPY_FLOAT_CONST(32768.0)); + int32_t echo_scaled = (int32_t)(MIN(mix, MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(32768.0)); + int32_t sample_scaled = (int32_t)(MIN(MICROPY_FLOAT_CONST(2.0) - mix, + MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(32768.0)); + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); if (MICROPY_FLOAT_C_FUN(fabs)(self->current_delay_ms - f_delay_ms) >= self->sample_ms) { recalculate_delay(self, f_delay_ms); @@ -340,16 +345,16 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t * next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate; for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { - word = (int16_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay); + word = (int16_t)((echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay_scaled) >> 15); echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int16_t)audiofilters_process_filter_chain(&self->filter, self->base.channel_count, !!echo_buffer_offset, word); } } else { echo = echo_buffer[echo_buffer_pos + echo_buffer_offset]; - word = (int16_t)(echo * decay); + word = (int16_t)((echo * decay_scaled) >> 15); echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int16_t)audiofilters_process_filter_chain(&self->filter, self->base.channel_count, !!echo_buffer_offset, word); } - word = (int16_t)(echo * MIN(mix, MICROPY_FLOAT_CONST(1.0))); + word = (int16_t)((echo * echo_scaled) >> 15); if (MP_LIKELY(self->base.bits_per_sample == 16)) { word_buffer[i] = word; @@ -418,13 +423,13 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t * next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate; } else { echo = echo_buffer[echo_buffer_pos + echo_buffer_offset]; - word = (int32_t)(echo * decay + sample_word); + word = ((echo * decay_scaled) >> 15) + sample_word; } if (MP_LIKELY(self->base.bits_per_sample == 16)) { if (self->freq_shift) { for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { - word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word); + word = ((echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay_scaled) >> 15) + sample_word; word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int16_t)audiofilters_process_filter_chain(&self->filter, self->base.channel_count, !!echo_buffer_offset, word); } @@ -435,7 +440,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t * } else { if (self->freq_shift) { for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { - word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word); + word = ((echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay_scaled) >> 15) + sample_word; // Do not have mix_down for 8 bit so just hard cap samples into 1 byte word = MIN(MAX(word, -128), 127); echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int8_t)audiofilters_process_filter_chain(&self->filter, self->base.channel_count, !!echo_buffer_offset, word); @@ -447,8 +452,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t * } } - word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) - + (echo * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = ((sample_word * sample_scaled) >> 15) + ((echo * echo_scaled) >> 15); word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); if (MP_LIKELY(self->base.bits_per_sample == 16)) { diff --git a/shared-module/audiodelays/MultiTapDelay.c b/shared-module/audiodelays/MultiTapDelay.c index d4cda65b0ed..eb912c82778 100644 --- a/shared-module/audiodelays/MultiTapDelay.c +++ b/shared-module/audiodelays/MultiTapDelay.c @@ -374,6 +374,11 @@ audioio_get_buffer_result_t audiodelays_multi_tap_delay_get_buffer(audiodelays_m mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); mp_float_t decay = synthio_block_slot_get_limited(&self->decay, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int32_t decay_scaled = (int32_t)(decay * MICROPY_FLOAT_CONST(32768.0)); + int32_t tap_scaled = (int32_t)(MIN(mix, MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(32768.0)); + int32_t sample_scaled = (int32_t)(MIN(MICROPY_FLOAT_CONST(2.0) - mix, + MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(32768.0)); + int16_t *sample_src = NULL; int8_t *sample_hsrc = NULL; if (self->sample != NULL) { @@ -424,7 +429,7 @@ audioio_get_buffer_result_t audiodelays_multi_tap_delay_get_buffer(audiodelays_m } // Apply decay and add sample - delay_word = (int32_t)(delay_word * decay) + sample_word; + delay_word = ((delay_word * decay_scaled) >> 15) + sample_word; if (MP_LIKELY(self->base.bits_per_sample == 16)) { delay_word = synthio_mix_down_sample(delay_word, SYNTHIO_MIX_DOWN_SCALE(2)); @@ -436,8 +441,7 @@ audioio_get_buffer_result_t audiodelays_multi_tap_delay_get_buffer(audiodelays_m } // Mix sample with tap output - word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) - + (word * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = ((sample_word * sample_scaled) >> 15) + ((word * tap_scaled) >> 15); word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); if (MP_LIKELY(self->base.bits_per_sample == 16)) { diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c index 37deaa06b58..dc7f7fe9809 100644 --- a/shared-module/audiofilters/Filter.c +++ b/shared-module/audiofilters/Filter.c @@ -195,6 +195,9 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int32_t wet_scaled = (int32_t)(mix * MICROPY_FLOAT_CONST(32768.0)); + int32_t dry_scaled = (int32_t)((MICROPY_FLOAT_CONST(1.0) - mix) * MICROPY_FLOAT_CONST(32768.0)); + if (mix <= MICROPY_FLOAT_CONST(0.01) || !self->filter.states) { // if mix is zero pure sample only or no biquad filter objects are provided for (uint32_t i = 0; i < n; i++) { if (MP_LIKELY(self->base.bits_per_sample == 16)) { @@ -238,15 +241,15 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o bool buf_offset = (j % self->base.channel_count) == 1; uint32_t k = j / self->base.channel_count; if (MP_LIKELY(self->base.bits_per_sample == 16)) { - word_buffer[i + j] = synthio_mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)), SYNTHIO_MIX_DOWN_SCALE(2)); + word_buffer[i + j] = synthio_mix_down_sample(((sample_src[i + j] * dry_scaled) >> 15) + ((self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * wet_scaled) >> 15), SYNTHIO_MIX_DOWN_SCALE(2)); if (!self->base.samples_signed) { word_buffer[i + j] ^= 0x8000; } } else { if (self->base.samples_signed) { - hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)); + hword_buffer[i + j] = (int8_t)(((sample_hsrc[i + j] * dry_scaled) >> 15) + ((self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * wet_scaled) >> 15)); } else { - hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * mix)) ^ 0x80; + hword_buffer[i + j] = (uint8_t)((((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * dry_scaled) >> 15) + ((self->filter_buffer[k + SYNTHIO_MAX_DUR * buf_offset] * wet_scaled) >> 15)) ^ 0x80; } } } diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index 464117fae8d..a171baf92d4 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -106,20 +106,19 @@ static inline uint32_t mult16signed(uint32_t val, int32_t lomul, int32_t himul) __asm__ volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack return val; #else - uint32_t result = 0; - for (int8_t i = 0; i < 2; i++) { - float mod_mul = (float)(i ? himul : lomul) / (float)((1 << 15) - 1); - int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)); - int32_t intermediate = (int32_t)(ai * mod_mul); - if (intermediate > SHRT_MAX) { - intermediate = SHRT_MAX; - } else if (intermediate < SHRT_MIN) { - intermediate = SHRT_MIN; - } - intermediate &= 0x0000FFFF; - result |= (((uint32_t)intermediate)) << (sizeof(int16_t) * 8 * i); + int32_t lo = ((int32_t)(int16_t)val * lomul) >> 15; + int32_t hi = ((int32_t)(int16_t)(val >> 16) * himul) >> 15; + if (lo > SHRT_MAX) { + lo = SHRT_MAX; + } else if (lo < SHRT_MIN) { + lo = SHRT_MIN; } - return result; + if (hi > SHRT_MAX) { + hi = SHRT_MAX; + } else if (hi < SHRT_MIN) { + hi = SHRT_MIN; + } + return ((uint32_t)hi << 16) | ((uint32_t)lo & 0xFFFF); #endif }