New try for linear interpolation.

Added a lowpass after chorus output.
master
Holger Wirtz 5 years ago
parent 0027b62530
commit 0e91d775f7
  1. 28
      MicroMDAEPiano.ino
  2. 6
      config.h
  3. 39
      effect_modulated_delay.cpp
  4. 3
      effect_modulated_delay.h

@ -58,6 +58,8 @@ AudioEffectModulatedDelay modchorus_r;
AudioEffectModulatedDelay modchorus_l; AudioEffectModulatedDelay modchorus_l;
AudioSynthWaveform modulator; AudioSynthWaveform modulator;
AudioFilterBiquad modulator_filter; AudioFilterBiquad modulator_filter;
AudioFilterBiquad chorus_filter_r;
AudioFilterBiquad chorus_filter_l;
AudioConnection patchCord0(queue_r, peak_r); AudioConnection patchCord0(queue_r, peak_r);
AudioConnection patchCord1(queue_l, peak_l); AudioConnection patchCord1(queue_l, peak_l);
AudioConnection patchCord2(queue_r, freeverb_r); AudioConnection patchCord2(queue_r, freeverb_r);
@ -70,20 +72,24 @@ AudioConnection patchCord8(modulator_filter, inverter);
AudioConnection patchCord9(inverter, 0, modchorus_l, 1); AudioConnection patchCord9(inverter, 0, modchorus_l, 1);
AudioConnection patchCord10(queue_r, 0, mixer_r, 0); AudioConnection patchCord10(queue_r, 0, mixer_r, 0);
AudioConnection patchCord11(queue_l, 0, mixer_l, 0); AudioConnection patchCord11(queue_l, 0, mixer_l, 0);
AudioConnection patchCord12(modchorus_r, 0, mixer_r, 2); AudioConnection patchCord12(modchorus_r, chorus_filter_r);
AudioConnection patchCord13(modchorus_l, 0, mixer_l, 2); AudioConnection patchCord13(modchorus_l, chorus_filter_l);
AudioConnection patchCord14(freeverb_r, 0, mixer_r, 1); AudioConnection patchCord14(chorus_filter_r, 0, mixer_r, 2);
AudioConnection patchCord15(freeverb_l, 0, mixer_l, 1); AudioConnection patchCord15(chorus_filter_l, 0, mixer_l, 2);
AudioConnection patchCord16(mixer_r, volume_r); AudioConnection patchCord16(modchorus_r, 0, mixer_r, 2);
AudioConnection patchCord17(mixer_l, volume_l); 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 #ifdef USB_AUDIO
AudioOutputUSB usb1; AudioOutputUSB usb1;
AudioConnection patchCord18(volume_r, 0, usb1, 0); AudioConnection patchCord22(volume_r, 0, usb1, 0);
AudioConnection patchCord19(volume_l, 0, usb1, 1); AudioConnection patchCord23(volume_l, 0, usb1, 1);
#endif #endif
AudioOutputI2S i2s1; AudioOutputI2S i2s1;
AudioConnection patchCord20(volume_r, 0, i2s1, 0); AudioConnection patchCord24(volume_r, 0, i2s1, 0);
AudioConnection patchCord21(volume_l, 0, i2s1, 1); AudioConnection patchCord25(volume_l, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; AudioControlSGTL5000 sgtl5000_1;
// Objects // Objects
@ -238,8 +244,10 @@ void setup()
inverter.gain(-1.0); // change phase for second modulated delay (faked stereo mode) inverter.gain(-1.0); // change phase for second modulated delay (faked stereo mode)
modchorus_r.offset(15.0); modchorus_r.offset(15.0);
modchorus_r.intensity(1.0); modchorus_r.intensity(1.0);
chorus_filter_r.setLowpass(0, 10000.0, CHORUS_MODULATOR_FILTER_Q);
modchorus_l.offset(15.0); modchorus_l.offset(15.0);
modchorus_l.intensity(1.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) // internal mixing of original signal(0), reverb(1) and chorus(2)
mixer_r.gain(VOL_MAIN, 0.5); mixer_r.gain(VOL_MAIN, 0.5);

@ -58,12 +58,12 @@
// CHORUS parameters // 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_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_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_MODULATOR_FILTER_Q 0.7
//#define CHORUS_INTERPOLATION_MODE 0 // no interpolation //#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_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 //* DEBUG OUTPUT SETTINGS

@ -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 // 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_idx = _delay_offset + ((float(*mp) / SHRT_MAX) * _modulation_intensity);
mod_fraction = modff(mod_idx, &mod_number); 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 // 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++) 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 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 *bp = int(round(spline->value(mod_fraction))); // use spline interpolated value
#else #else
// Simple interpolation // linear interpolation
int16_t c_mod_idx = (_circ_idx + int(round(mod_idx))) % _delay_length; c_mod_idx = _circ_idx - round(mod_idx);
float value1, value2; 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--;
if (c_mod_idx < 0) 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]; idx[0] = 0;
value2 = _delayline[_delay_length + c_mod_idx]; idx[1] = _delay_length - 1;
} }
else else if (c_mod_idx + 1 >= _delay_length)
{ {
value1 = _delayline[c_mod_idx - 1]; idx[0] = c_mod_idx;
value2 = _delayline[c_mod_idx]; idx[1] = 0;
} }
if (mod_fraction < 0)
*bp = int(round((1.0 + mod_fraction) * value1 + fabs(mod_fraction) * value2));
else 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 #endif
bp++; // next audio data bp++; // next audio data
mp++; // next modulation data mp++; // next modulation data

@ -56,10 +56,13 @@ class AudioEffectModulatedDelay :
uint16_t _delay_offset; uint16_t _delay_offset;
uint16_t _modulation_intensity; uint16_t _modulation_intensity;
uint16_t _delay_length; uint16_t _delay_length;
int16_t c_mod_idx;
#ifdef CHORUS_INTERPOLATION_MODE #ifdef CHORUS_INTERPOLATION_MODE
float x[CHORUS_INTERPOLATION_WINDOW_SIZE]; float x[CHORUS_INTERPOLATION_WINDOW_SIZE];
float y[CHORUS_INTERPOLATION_WINDOW_SIZE]; float y[CHORUS_INTERPOLATION_WINDOW_SIZE];
Spline* spline; Spline* spline;
#else
uint16_t idx[2];
#endif #endif
}; };

Loading…
Cancel
Save