From 0e91d775f72bdf934e16a821211ae6c517b9b004 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Fri, 12 Jul 2019 14:27:41 +0200 Subject: [PATCH] New try for linear interpolation. Added a lowpass after chorus output. --- MicroMDAEPiano.ino | 36 +++++++++++++++++++++-------------- config.h | 6 +++--- effect_modulated_delay.cpp | 39 ++++++++++++++++++++------------------ effect_modulated_delay.h | 3 +++ 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/MicroMDAEPiano.ino b/MicroMDAEPiano.ino index 8ea1f7a..34ca2e6 100644 --- a/MicroMDAEPiano.ino +++ b/MicroMDAEPiano.ino @@ -58,6 +58,8 @@ AudioEffectModulatedDelay modchorus_r; AudioEffectModulatedDelay modchorus_l; AudioSynthWaveform modulator; AudioFilterBiquad modulator_filter; +AudioFilterBiquad chorus_filter_r; +AudioFilterBiquad chorus_filter_l; AudioConnection patchCord0(queue_r, peak_r); AudioConnection patchCord1(queue_l, peak_l); AudioConnection patchCord2(queue_r, freeverb_r); @@ -70,20 +72,24 @@ AudioConnection patchCord8(modulator_filter, inverter); AudioConnection patchCord9(inverter, 0, modchorus_l, 1); AudioConnection patchCord10(queue_r, 0, mixer_r, 0); AudioConnection patchCord11(queue_l, 0, mixer_l, 0); -AudioConnection patchCord12(modchorus_r, 0, mixer_r, 2); -AudioConnection patchCord13(modchorus_l, 0, mixer_l, 2); -AudioConnection patchCord14(freeverb_r, 0, mixer_r, 1); -AudioConnection patchCord15(freeverb_l, 0, mixer_l, 1); -AudioConnection patchCord16(mixer_r, volume_r); -AudioConnection patchCord17(mixer_l, volume_l); +AudioConnection patchCord12(modchorus_r, chorus_filter_r); +AudioConnection patchCord13(modchorus_l, chorus_filter_l); +AudioConnection patchCord14(chorus_filter_r, 0, mixer_r, 2); +AudioConnection patchCord15(chorus_filter_l, 0, mixer_l, 2); +AudioConnection patchCord16(modchorus_r, 0, mixer_r, 2); +AudioConnection patchCord17(modchorus_l, 0, mixer_l, 2); +AudioConnection patchCord18(freeverb_r, 0, mixer_r, 1); +AudioConnection patchCord19(freeverb_l, 0, mixer_l, 1); +AudioConnection patchCord20(mixer_r, volume_r); +AudioConnection patchCord21(mixer_l, volume_l); #ifdef USB_AUDIO AudioOutputUSB usb1; -AudioConnection patchCord18(volume_r, 0, usb1, 0); -AudioConnection patchCord19(volume_l, 0, usb1, 1); +AudioConnection patchCord22(volume_r, 0, usb1, 0); +AudioConnection patchCord23(volume_l, 0, usb1, 1); #endif AudioOutputI2S i2s1; -AudioConnection patchCord20(volume_r, 0, i2s1, 0); -AudioConnection patchCord21(volume_l, 0, i2s1, 1); +AudioConnection patchCord24(volume_r, 0, i2s1, 0); +AudioConnection patchCord25(volume_l, 0, i2s1, 1); AudioControlSGTL5000 sgtl5000_1; // Objects @@ -238,8 +244,10 @@ void setup() inverter.gain(-1.0); // change phase for second modulated delay (faked stereo mode) modchorus_r.offset(15.0); modchorus_r.intensity(1.0); + chorus_filter_r.setLowpass(0, 10000.0, CHORUS_MODULATOR_FILTER_Q); modchorus_l.offset(15.0); modchorus_l.intensity(1.0); + chorus_filter_l.setLowpass(0, 10000.0, CHORUS_MODULATOR_FILTER_Q); // internal mixing of original signal(0), reverb(1) and chorus(2) mixer_r.gain(VOL_MAIN, 0.5); @@ -255,12 +263,12 @@ void setup() // init random generator srand(analogRead(A0)); - Serial.println(F("")); + Serial.println(F("")); #if defined (SHOW_DEBUG) && defined (SHOW_CPU_LOAD_MSEC) - Serial.println(); - show_cpu_and_mem_usage(); - cpu_mem_millis = 0; + Serial.println(); + show_cpu_and_mem_usage(); + cpu_mem_millis = 0; #endif } diff --git a/config.h b/config.h index 60a94cd..f120947 100644 --- a/config.h +++ b/config.h @@ -58,12 +58,12 @@ // CHORUS parameters #define CHORUS_DELAY_LENGTH_SAMPLES (15*AUDIO_BLOCK_SAMPLES) // one AUDIO_BLOCK_SAMPLES = 2.902ms; you need doubled length, e.g. delay point is 20ms, so you need up to 40ms delay! #define CHORUS_WAVEFORM WAVEFORM_TRIANGLE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE -#define CHORUS_MODULATOR_FILTER_FRQ 1000 +#define CHORUS_MODULATOR_FILTER_FRQ 500 #define CHORUS_MODULATOR_FILTER_Q 0.7 //#define CHORUS_INTERPOLATION_MODE 0 // no interpolation -#define CHORUS_INTERPOLATION_MODE 1 // linear interpolation +//#define CHORUS_INTERPOLATION_MODE 1 // linear interpolation //#define CHORUS_INTERPOLATION_MODE Catmull // spline interpolation -#define CHORUS_INTERPOLATION_WINDOW_SIZE 3 // only uneven numbers bigger than 3!!! +#define CHORUS_INTERPOLATION_WINDOW_SIZE 5 // only uneven numbers bigger than 3!!! //************************************************************************************************* //* DEBUG OUTPUT SETTINGS diff --git a/effect_modulated_delay.cpp b/effect_modulated_delay.cpp index 9368585..5a020de 100644 --- a/effect_modulated_delay.cpp +++ b/effect_modulated_delay.cpp @@ -106,10 +106,10 @@ void AudioEffectModulatedDelay::update(void) // The index is located around the half of the delay length multiplied by the current amount of the modulator mod_idx = _delay_offset + ((float(*mp) / SHRT_MAX) * _modulation_intensity); mod_fraction = modff(mod_idx, &mod_number); -#ifdef CHORUS_INTERPOLATION_MODE - // Spline interpolation // Generate a an array with the size of CHORUS_INTERPOLATION_WINDOW_SIZE of x/y values around mod_idx for interpolation - int16_t c_mod_idx = _circ_idx - int(round(mod_idx)); // This is the pointer to the value in the circular buffer at the current modulation index +#ifdef CHORUS_INTERPOLATION_MODE + // spline interpolation + c_mod_idx = _circ_idx - int(mod_idx); // This is the pointer to the value in the circular buffer at the current modulation index for (j = (CHORUS_INTERPOLATION_WINDOW_SIZE / -2), c = 0; j <= (CHORUS_INTERPOLATION_WINDOW_SIZE / 2); j++, c++) { int16_t jc_mod_idx = (c_mod_idx + j) % _delay_length; // The modulation index pointer plus the value of the current window pointer @@ -121,26 +121,29 @@ void AudioEffectModulatedDelay::update(void) } *bp = int(round(spline->value(mod_fraction))); // use spline interpolated value #else - // Simple interpolation - int16_t c_mod_idx = (_circ_idx + int(round(mod_idx))) % _delay_length; - float value1, value2; - - if (c_mod_idx < 0) + // linear interpolation + c_mod_idx = _circ_idx - round(mod_idx); + if (mod_idx < 0.0) // c_mod_idx is the pointer to the value in the circular buffer at the current modulation index + c_mod_idx--; + c_mod_idx %= _delay_length; // The modulation index pointer plus the value of the current window pointer + if (c_mod_idx < 0) // check for negative offsets and correct them + c_mod_idx += _delay_length; + if (c_mod_idx - 1 < 0) { - value1 = _delayline[_delay_length + c_mod_idx - 1]; - value2 = _delayline[_delay_length + c_mod_idx]; + idx[0] = 0; + idx[1] = _delay_length - 1; } - else + else if (c_mod_idx + 1 >= _delay_length) { - value1 = _delayline[c_mod_idx - 1]; - value2 = _delayline[c_mod_idx]; + idx[0] = c_mod_idx; + idx[1] = 0; } - - if (mod_fraction < 0) - *bp = int(round((1.0 + mod_fraction) * value1 + fabs(mod_fraction) * value2)); else - *bp = int(round(mod_fraction * value1 + (1.0 - mod_fraction) * value2)); - + { + idx[0] = c_mod_idx; + idx[1] = c_mod_idx + 1; + } + *bp = round(float(_delayline[idx[0]]) * (1.0 - mod_fraction) + float(_delayline[idx[1]]) * mod_fraction); #endif bp++; // next audio data mp++; // next modulation data diff --git a/effect_modulated_delay.h b/effect_modulated_delay.h index a521d29..bb60fa4 100644 --- a/effect_modulated_delay.h +++ b/effect_modulated_delay.h @@ -56,10 +56,13 @@ class AudioEffectModulatedDelay : uint16_t _delay_offset; uint16_t _modulation_intensity; uint16_t _delay_length; + int16_t c_mod_idx; #ifdef CHORUS_INTERPOLATION_MODE float x[CHORUS_INTERPOLATION_WINDOW_SIZE]; float y[CHORUS_INTERPOLATION_WINDOW_SIZE]; Spline* spline; +#else + uint16_t idx[2]; #endif };