From 68508e91482b2ee39d0b9e7de3c34dcc68e61709 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Thu, 23 Dec 2021 19:16:17 +0100 Subject: [PATCH] Fixes for chorus and stereo panning. --- MicroDexed.ino | 52 +++++++++------------------ UI.hpp | 4 +-- effect_modulated_delay.cpp | 72 ++++++++++++++++++++++++++++++++++++-- effect_modulated_delay.h | 9 +++++ effect_stereo_panorama.cpp | 9 ++--- 5 files changed, 101 insertions(+), 45 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index bcab22a..053e3d4 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -85,9 +85,7 @@ AudioSynthWaveform ep_chorus_modulator; #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT AudioFilterBiquad ep_modchorus_filter; #endif -AudioEffectModulatedDelay ep_modchorus_r; -AudioEffectModulatedDelay ep_modchorus_l; -AudioAmplifier ep_chorus_inverter; +AudioEffectModulatedDelayStereo ep_modchorus; AudioMixer<2> ep_chorus_mixer_r; AudioMixer<2> ep_chorus_mixer_l; #endif @@ -254,19 +252,16 @@ AudioConnection patchCord[] = { #if defined(USE_FX) {ep_stereo_panorama, 0, ep_chorus_mixer_r, 0}, {ep_stereo_panorama, 1, ep_chorus_mixer_l, 0}, - {ep_stereo_panorama, 0, ep_modchorus_r, 0}, - {ep_stereo_panorama, 1, ep_modchorus_l, 0}, + {ep_stereo_panorama, 0, ep_modchorus, 0}, + {ep_stereo_panorama, 1, ep_modchorus, 1}, #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT {ep_chorus_modulator, 0, ep_modchorus_filter, 0}, - {ep_modchorus_filter, 0, ep_modchorus_r, 1}, - {ep_modchorus_filter, 0, ep_chorus_inverter, 0}, + {ep_modchorus_filter, 0, ep_modchorus, 2}, #else - {ep_chorus_modulator, 0, ep_modchorus_r, 1}, - {ep_chorus_modulator, 0, ep_chorus_inverter, 0}, + {ep_chorus_modulator, 0, ep_modchorus, 2}, #endif - {ep_chorus_inverter, 0, ep_modchorus_l, 1}, - {ep_modchorus_r, 0, ep_chorus_mixer_r, 1}, - {ep_modchorus_l, 0, ep_chorus_mixer_l, 1}, + {ep_modchorus, 0, ep_chorus_mixer_r, 1}, + {ep_modchorus, 1, ep_chorus_mixer_l, 1}, {ep_chorus_mixer_r, 0, reverb_mixer_r, REVERB_MIX_CH_EPIANO}, {ep_chorus_mixer_l, 0, reverb_mixer_l, REVERB_MIX_CH_EPIANO}, {ep_stereo_panorama, 0, master_mixer_r, MASTER_MIX_CH_EPIANO}, @@ -588,41 +583,26 @@ void setup() #if defined(USE_EPIANO) // EP_CHORUS ep_delayline_r = (int16_t*)malloc(MOD_DELAY_SAMPLE_BUFFER * sizeof(int16_t)); - if (ep_delayline_r != NULL) - { - memset(ep_delayline_r, 0, MOD_DELAY_SAMPLE_BUFFER * sizeof(int16_t)); - if (!ep_modchorus_r.begin(ep_delayline_r, MOD_DELAY_SAMPLE_BUFFER)) - { -#ifdef DEBUG - Serial.println(F("AudioEffectModulatedDelay R - begin failed EP")); -#endif - while (1); - } - } - else + if (ep_delayline_r == NULL) { #ifdef DEBUG Serial.println(F("AudioEffectModulatedDelay R - memory allocation failed EP")); #endif while (1); } - ep_delayline_l = (int16_t*)malloc(MOD_DELAY_SAMPLE_BUFFER * sizeof(int16_t)); - if (ep_delayline_l != NULL) + if (ep_delayline_l == NULL) { - memset(ep_delayline_l, 0, MOD_DELAY_SAMPLE_BUFFER * sizeof(int16_t)); - if (!ep_modchorus_l.begin(ep_delayline_l, MOD_DELAY_SAMPLE_BUFFER)) - { #ifdef DEBUG - Serial.println(F("AudioEffectModulatedDelay L - begin failed EP")); + Serial.println(F("AudioEffectModulatedDelay L - memory allocation failed EP")); #endif - while (1); - } + while (1); } - else + + if (!ep_modchorus.begin(ep_delayline_r, ep_delayline_l, MOD_DELAY_SAMPLE_BUFFER)) { #ifdef DEBUG - Serial.println(F("AudioEffectModulatedDelay L - memory allocation failed EP")); + Serial.println(F("AudioEffectModulatedDelayStereo - begin failed EP")); #endif while (1); } @@ -641,7 +621,6 @@ void setup() ep_chorus_mixer_l.gain(0, 1.0); ep_chorus_mixer_r.gain(1, mapfloat(EP_CHORUS_LEVEL_DEFAULT, EP_CHORUS_LEVEL_MIN, EP_CHORUS_LEVEL_MAX, 0.0, 0.5)); ep_chorus_mixer_l.gain(1, mapfloat(EP_CHORUS_LEVEL_DEFAULT, EP_CHORUS_LEVEL_MIN, EP_CHORUS_LEVEL_MAX, 0.0, 0.5)); - ep_chorus_inverter.gain(-1.0); ep_stereo_panorama.panorama(mapfloat(EP_PANORAMA_DEFAULT, EP_PANORAMA_MIN, EP_PANORAMA_MAX, -1.0, 1.0)); #endif #endif @@ -797,6 +776,8 @@ void setup() Serial.println(F("")); #endif + ep_modchorus.set_bypass(true); + strcpy(seq.seq_name, "INIT Perf"); LCDML.OTHER_jumpToFunc(UI_func_voice_select); } @@ -2608,7 +2589,6 @@ void set_fx_params(void) ep_chorus_mixer_l.gain(0, 1.0); ep_chorus_mixer_r.gain(1, mapfloat(configuration.fx.ep_chorus_level, EP_CHORUS_LEVEL_MIN, EP_CHORUS_LEVEL_MAX, 0.0, 0.5)); ep_chorus_mixer_l.gain(1, mapfloat(configuration.fx.ep_chorus_level, EP_CHORUS_LEVEL_MIN, EP_CHORUS_LEVEL_MAX, 0.0, 0.5)); - ep_chorus_inverter.gain(-1.0); #endif #endif diff --git a/UI.hpp b/UI.hpp index 51a5bd6..b509f72 100644 --- a/UI.hpp +++ b/UI.hpp @@ -132,9 +132,7 @@ extern AudioSynthWaveform ep_chorus_modulator; #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT extern AudioFilterBiquad ep_modchorus_filter; #endif -extern AudioEffectModulatedDelay ep_modchorus_r; -extern AudioEffectModulatedDelay ep_modchorus_l; -extern AudioAmplifier ep_chorus_inverter; +extern AudioEffectModulatedDelayStereo ep_modchorus; extern AudioMixer<2> ep_chorus_mixer_r; extern AudioMixer<2> ep_chorus_mixer_l; extern AudioMixer<2> ep_delay_fb_mixer_r; diff --git a/effect_modulated_delay.cpp b/effect_modulated_delay.cpp index e2eb001..909afb3 100644 --- a/effect_modulated_delay.cpp +++ b/effect_modulated_delay.cpp @@ -111,6 +111,19 @@ void AudioEffectModulatedDelay::update(void) if (!modulation) modulation = (audio_block_t*)&zeroblock; + if (bypass == true) + { + if (modulation != (audio_block_t*)&zeroblock) + release(modulation); + + if (block != (audio_block_t*)&zeroblock) + { + transmit(block, 0); + release(block); + } + return; + } + if (block && modulation) { int16_t *bp; @@ -165,6 +178,16 @@ void AudioEffectModulatedDelay::update(void) } } +void AudioEffectModulatedDelay::set_bypass(bool b) +{ + bypass = b; +} + +bool AudioEffectModulatedDelay::get_bypass(void) +{ + return (bypass); +} + boolean AudioEffectModulatedDelayStereo::begin(short *delayline_l, short *delayline_r, uint16_t d_length) { #if 0 @@ -200,6 +223,8 @@ boolean AudioEffectModulatedDelayStereo::begin(short *delayline_l, short *delayl memset(_delayline[1], 0, _delay_length * sizeof(int16_t)); _delay_offset[1] = _delay_length >> 1 ; + stereo = true; + return (true); } @@ -213,7 +238,7 @@ void AudioEffectModulatedDelayStereo::update(void) audio_block_t *block[2]; audio_block_t *modulation; - if (_delayline == NULL) + if (_delayline[0] == NULL || _delayline[1] == NULL) return; block[0] = receiveWritable(0); @@ -228,6 +253,25 @@ void AudioEffectModulatedDelayStereo::update(void) if (!modulation) modulation = (audio_block_t*)&zeroblock; + if (bypass == true) + { + if (modulation != (audio_block_t*)&zeroblock) + release(modulation); + + if (block[0] != (audio_block_t*)&zeroblock) + { + transmit(block[0], 0); + release(block[0]); + } + + if (block[1] != (audio_block_t*)&zeroblock) + { + transmit(block[1], 0); + release(block[1]); + } + return; + } + if (block[0] && block[1] && modulation) { int16_t *bp[2]; @@ -274,7 +318,11 @@ void AudioEffectModulatedDelayStereo::update(void) // RIGHT // calculate the modulation-index as a floating point number for interpolation - mod_index = -1.0 * *mp * _delay_offset[0]; + if (stereo == true) + mod_index = -1.0 * *mp * _delay_offset[0]; + else + mod_index = *mp * _delay_offset[0]; + mod_fraction = modff(mod_index, &mod_number); // split float of mod_index into integer (= mod_number) and fraction part // write data into circular buffer (delayline) @@ -316,3 +364,23 @@ void AudioEffectModulatedDelayStereo::update(void) release(block[1]); } } + +void AudioEffectModulatedDelayStereo::set_stereo(bool s) +{ + stereo = s; +} + +bool AudioEffectModulatedDelayStereo::get_stereo(void) +{ + return (stereo); +} + +void AudioEffectModulatedDelayStereo::set_bypass(bool b) +{ + bypass = b; +} + +bool AudioEffectModulatedDelayStereo::get_bypass(void) +{ + return (bypass); +} diff --git a/effect_modulated_delay.h b/effect_modulated_delay.h index 624b671..9710dd9 100644 --- a/effect_modulated_delay.h +++ b/effect_modulated_delay.h @@ -45,6 +45,8 @@ class AudioEffectModulatedDelay : boolean begin(short *delayline, uint16_t delay_length); virtual void update(void); virtual uint16_t get_delay_length(void); + virtual void set_bypass(bool b); + virtual bool get_bypass(void); private: audio_block_t *inputQueueArray[2]; @@ -53,6 +55,7 @@ class AudioEffectModulatedDelay : uint16_t _delay_length; // calculated number of samples of the delay int16_t cb_mod_index; // current read pointer with modulation for the circular buffer uint16_t _delay_offset; + bool bypass; }; class AudioEffectModulatedDelayStereo : @@ -66,6 +69,10 @@ class AudioEffectModulatedDelayStereo : boolean begin(short *delayline_l, short *delayline_r, uint16_t delay_length); virtual void update(void); virtual uint16_t get_delay_length(void); + virtual void set_stereo(bool s); + virtual bool get_stereo(void); + virtual void set_bypass(bool b); + virtual bool get_bypass(void); private: audio_block_t *inputQueueArray[3]; @@ -74,5 +81,7 @@ class AudioEffectModulatedDelayStereo : uint16_t _delay_length; // calculated number of samples of the delay int16_t cb_mod_index[2]; // current read pointer with modulation for the circular buffer uint16_t _delay_offset[2]; + bool stereo; + bool bypass; }; #endif diff --git a/effect_stereo_panorama.cpp b/effect_stereo_panorama.cpp index 3252f31..524285b 100644 --- a/effect_stereo_panorama.cpp +++ b/effect_stereo_panorama.cpp @@ -68,7 +68,7 @@ inline float mapfloat(float val, float in_min, float in_max, float out_min, floa void AudioEffectStereoPanorama::panorama(float p) { - pan = mapfloat(p, 0.0, 1.0, -1.0, 1.0); + pan = mapfloat(p, -1.0, 1.0, -1.0, 1.0); } void AudioEffectStereoPanorama::update(void) @@ -98,13 +98,14 @@ void AudioEffectStereoPanorama::update(void) { if (pan > 0.0) { - out_f[0][n] = (pan / 2.0 * in_f[1][n]) + ((1.0 - pan) / 2.0 * in_f[0][n]); + out_f[0][n] = (pan * in_f[1][n]) + ((1.0 - pan) * in_f[0][n]); out_f[1][n] = (1.0 - pan) * in_f[1][n]; } else { - out_f[1][n] = (pan / 2.0 * in_f[0][n]) + ((1.0 - pan) / 2.0 * in_f[1][n]); - out_f[0][n] = (1.0 - pan) * in_f[0][n]; + float _pan_ = fabs(pan); + out_f[1][n] = (_pan_ * in_f[0][n]) + ((1.0 - _pan_) * in_f[1][n]); + out_f[0][n] = (1.0 - _pan_) * in_f[0][n]; } } else