Several fixes and additions for filtering chorus modulator nd output.

master
Holger Wirtz 5 years ago
parent 4d04f28815
commit 296fa08774
  1. 33
      MicroMDAEPiano.ino
  2. 9
      UI.hpp
  3. 3
      config.h
  4. 51
      effect_modulated_delay.cpp
  5. 4
      effect_modulated_delay.h

@ -56,9 +56,7 @@ AudioAmplifier volume_l;
AudioAmplifier inverter;
AudioEffectModulatedDelay modchorus_r;
AudioEffectModulatedDelay modchorus_l;
AudioSynthWaveform modulator1;
AudioSynthWaveform modulator2;
AudioMixer4 modulator_mixer;
AudioSynthWaveform modulator;
AudioFilterStateVariable chorus_filter_r;
AudioFilterStateVariable chorus_filter_l;
AudioConnection patchCord0(queue_r, peak_r);
@ -67,10 +65,8 @@ AudioConnection patchCord2(queue_r, freeverb_r);
AudioConnection patchCord3(queue_l, freeverb_l);
AudioConnection patchCord4(queue_r, 0, modchorus_r, 0);
AudioConnection patchCord5(queue_l, 0, modchorus_l, 0);
AudioConnection patchCord6(modulator1, 0, modulator_mixer, 0);
AudioConnection patchCord7(modulator2, 0, modulator_mixer, 1);
AudioConnection patchCord8(modulator_mixer, 0, modchorus_r, 1);
AudioConnection patchCord9(modulator_mixer, inverter);
AudioConnection patchCord8(modulator, 0, modchorus_r, 1);
AudioConnection patchCord9(modulator, inverter);
AudioConnection patchCord10(inverter, 0, modchorus_l, 1);
AudioConnection patchCord11(queue_r, 0, mixer_r, 0);
AudioConnection patchCord12(queue_l, 0, mixer_l, 0);
@ -237,26 +233,17 @@ void setup()
}
// chorus modulation fixed
modulator1.begin(CHORUS_WAVEFORM_MOD1);
modulator1.phase(0);
modulator1.amplitude(1.0);
modulator1.offset(0.0);
modulator2.begin(CHORUS_WAVEFORM_MOD2);
modulator2.phase(0);
modulator2.amplitude(1.0);
modulator2.offset(0.0);
modulator_mixer.gain(0, 0.5);
modulator_mixer.gain(1, 0.5);
inverter.gain(1.0); // change phase for second modulated delay (faked stereo mode)
//modulator_filter.frequency(15000);
//modulator_filter.resonance(0.7);
//modulator_filter.octaveControl(1);
modulator.begin(CHORUS_WAVEFORM_MOD);
modulator.phase(0);
modulator.amplitude(1.0);
modulator.offset(0.0);
inverter.gain(-1.0); // change phase for second modulated delay (faked stereo mode)
chorus_filter_r.frequency(3500);
chorus_filter_r.resonance(0.7);
chorus_filter_r.octaveControl(2);
chorus_filter_r.octaveControl(1);
chorus_filter_l.frequency(3500);
chorus_filter_l.resonance(0.7);
chorus_filter_l.octaveControl(2);
chorus_filter_l.octaveControl(1);
modchorus_r.offset(15.0);
modchorus_l.offset(15.0);

@ -121,8 +121,7 @@ extern void eeprom_config_write(uint8_t value);
extern AudioControlSGTL5000 sgtl5000_1;
extern AudioEffectFreeverb freeverb_r;
extern AudioEffectFreeverb freeverb_l;
extern AudioSynthWaveform modulator1;
extern AudioSynthWaveform modulator2;
extern AudioSynthWaveform modulator;
extern AudioEffectModulatedDelay modchorus_r;
extern AudioEffectModulatedDelay modchorus_l;
extern AudioMixer4 mixer_r;
@ -2038,8 +2037,7 @@ void set_chorus_frequency(uint8_t value)
Serial.print(F("Set CHORUS_FREQUENCY "));
Serial.println(value);
#endif
modulator1.frequency(float(value) / 10);
modulator2.frequency(float(value) / 10);
modulator.frequency(float(value) / 10);
configuration.chorus_frequency = value;
}
@ -2059,8 +2057,7 @@ void set_chorus_intensity(uint8_t value)
Serial.print(F("Set CHORUS_INTENSITY "));
Serial.println(value);
#endif
modulator1.amplitude(mapfloat(float(value), ENC_CHORUS_INTENSITY_MIN, ENC_CHORUS_INTENSITY_MAX, 0.0, 1.0));
modulator2.amplitude(mapfloat(float(value), ENC_CHORUS_INTENSITY_MIN, ENC_CHORUS_INTENSITY_MAX, 0.0, 1.0));
modulator.amplitude(mapfloat(float(value), ENC_CHORUS_INTENSITY_MIN, ENC_CHORUS_INTENSITY_MAX, 0.0, 1.0));
configuration.chorus_intensity = value;
}

@ -56,8 +56,7 @@
#define USE_XFADE_DATA 1
// CHORUS parameters
#define CHORUS_DELAY_LENGTH_SAMPLES (15*AUDIO_BLOCK_SAMPLES) // one AUDIO_BLOCK_SAMPLES = 2.902ms
#define CHORUS_WAVEFORM_MOD1 WAVEFORM_SINE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE
#define CHORUS_WAVEFORM_MOD2 WAVEFORM_TRIANGLE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE
#define CHORUS_WAVEFORM_MOD WAVEFORM_TRIANGLE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE
//*************************************************************************************************
//* DEBUG OUTPUT SETTINGS
//*************************************************************************************************

@ -60,37 +60,25 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length)
_delayline = delayline;
_delay_length = d_length;
set_modulator_filter_coeffs(1.0, configuration.chorus_frequency / 10, 1.0); // gain, center frerquency
modulator_filter_data = {1, &modulator_filter_state, modulator_filter_coeffs};
set_modulator_filter_coeffs();
modulator_filter_data = {1, modulator_filter_state, modulator_filter_coeffs};
return (true);
}
void AudioEffectModulatedDelay::set_modulator_filter_coeffs(float gain, float fc, float width)
void AudioEffectModulatedDelay::set_modulator_filter_coeffs(void)
{
// modulator filter
// coefficients calculated with "IOWA Hills IIR Filter Designer 6.5", http://www.iowahills.com/8DownloadPage.html
// "IOWA Hills IIR Filter Designer 6.5", http://www.iowahills.com/8DownloadPage.html
// Example: https://web.fhnw.ch/technik/projekte/eit/Fruehling2016/MuelZum/html/parametric_equalizer_example_8c-example.html
/* float32_t A = sqrt(powf(10, gain / 20.0f));
float32_t w0 = 2.0f * PI * fc / ((float32_t)AUDIO_SAMPLE_RATE_EXACT);
float32_t cosw0 = cosf(w0);
float32_t sinw0 = sinf(w0);
float32_t alpha = sinw0 / (2.0f * width);
float32_t a0 = 1.0f + alpha / A;
modulator_filter_coeffs[0] = (1.0f + alpha * A) / a0; // b0
modulator_filter_coeffs[1] = (-2.0f * cosw0) / a0; // b1
modulator_filter_coeffs[2] = (1.0f - alpha * A) / a0; // b2
modulator_filter_coeffs[3] = -(2.0f * cosw0) / -a0; // -a1
modulator_filter_coeffs[4] = (1.0f - alpha / A) / -a0; // -a2 */
// OmegaC = 0.1, SR = 44117.64706, Fc = 2.21 kHz, N=2
modulator_filter_coeffs[0] = 0.020727217357494492; // b0
modulator_filter_coeffs[1] = 0.020727217357494492; // b1
modulator_filter_coeffs[2] = 0.020727217357494492; // b2
modulator_filter_coeffs[3] = 1.563046149664217620; // -a1
modulator_filter_coeffs[4] = -0.642749223719756180; // -a2
// Coeeficients calculated with https://arachnoid.com/BiQuadDesigner/index.html
// SR = 44110, Fc = 400 Hz; Q=0.707
modulator_filter_coeffs[0] = 7.80321719e-4; // b0
modulator_filter_coeffs[1] = 0.00156064; // b1
modulator_filter_coeffs[2] = 7.80321719e-4; // b2
modulator_filter_coeffs[3] = 1.91943335; // -a1
modulator_filter_coeffs[4] = -0.92255463; // -a2
}
void AudioEffectModulatedDelay::update(void)
@ -116,7 +104,7 @@ void AudioEffectModulatedDelay::update(void)
bp = block->data;
arm_q15_to_float(modulation->data, modulation_f32, AUDIO_BLOCK_SAMPLES);
//arm_biquad_cascade_df1_f32(&modulator_filter_data, modulation_f32, modulation_f32, AUDIO_BLOCK_SAMPLES);
arm_biquad_cascade_df1_f32(&modulator_filter_data, modulation_f32, modulation_f32, AUDIO_BLOCK_SAMPLES);
mp = modulation_f32;
for (uint16_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
@ -131,9 +119,9 @@ void AudioEffectModulatedDelay::update(void)
mod_fraction = modff(mod_index, &mod_number); // split float of mod_index into integer (= mod_number) and fraction part
// calculate modulation index into circular buffer
cb_mod_index = (_cb_index - (_delay_offset + int(mod_index)));
if (cb_mod_index >= _delay_length)
cb_mod_index -= _delay_length;
cb_mod_index = (_cb_index - (_delay_offset + mod_number));
/* if (cb_mod_index >= _delay_length)
cb_mod_index -= _delay_length; */
if (cb_mod_index < 0) // check for negative offsets and correct them
cb_mod_index += _delay_length;
@ -143,6 +131,7 @@ void AudioEffectModulatedDelay::update(void)
cb_mod_index_neighbor = _delay_length;
else
cb_mod_index_neighbor = cb_mod_index - 1;
*bp = round(float(_delayline[cb_mod_index]) * mod_fraction + float(_delayline[cb_mod_index_neighbor]) * (1.0 - mod_fraction));
}
else
{
@ -150,12 +139,8 @@ void AudioEffectModulatedDelay::update(void)
cb_mod_index_neighbor = 0;
else
cb_mod_index_neighbor = cb_mod_index + 1;
}
if (*mp < 0.0)
*bp = round(float(_delayline[cb_mod_index]) * mod_fraction + float(_delayline[cb_mod_index_neighbor]) * (1.0 - mod_fraction));
else
*bp = round(float(_delayline[cb_mod_index_neighbor]) * mod_fraction + float(_delayline[cb_mod_index]) * (1.0 - mod_fraction));
}
// push the pointers forward
bp++; // next audio data

@ -49,7 +49,7 @@ class AudioEffectModulatedDelay :
virtual float offset(float offset_value);
private:
void set_modulator_filter_coeffs(float gain, float fc, float width);
void set_modulator_filter_coeffs(void);
audio_block_t *inputQueueArray[2];
int16_t *_delayline; // pointer for the circular buffer
uint16_t _cb_index; // current write pointer of the circular buffer
@ -57,7 +57,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
arm_biquad_casd_df1_inst_f32 modulator_filter_data;
float32_t modulator_filter_state;
float32_t modulator_filter_state[4];
float32_t modulator_filter_coeffs[5];
};

Loading…
Cancel
Save