|
|
|
@ -26,9 +26,6 @@ |
|
|
|
|
#include "arm_math.h" |
|
|
|
|
#include "effect_modulated_delay.h" |
|
|
|
|
#include "config.h" |
|
|
|
|
#include "DCfilter.h" |
|
|
|
|
#include "OnePoleLP.h" |
|
|
|
|
#include "limits.h" |
|
|
|
|
|
|
|
|
|
extern config_t configuration; |
|
|
|
|
|
|
|
|
@ -52,7 +49,6 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length) |
|
|
|
|
_delay_length = 0; |
|
|
|
|
_delay_offset = 0.0; |
|
|
|
|
_cb_index = 0; |
|
|
|
|
z1 = 0; |
|
|
|
|
|
|
|
|
|
if (delayline == NULL) { |
|
|
|
|
return (false); |
|
|
|
@ -63,13 +59,11 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length) |
|
|
|
|
|
|
|
|
|
_delayline = delayline; |
|
|
|
|
_delay_length = d_length; |
|
|
|
|
memset(_delayline, 0, d_length); |
|
|
|
|
|
|
|
|
|
set_modulator_filter_coeffs(); |
|
|
|
|
modulator_filter_data = {1, modulator_filter_state, modulator_filter_coeffs}; |
|
|
|
|
|
|
|
|
|
lp = new OnePoleLP(); |
|
|
|
|
dcFilter = new DCfilter(0.9); |
|
|
|
|
|
|
|
|
|
return (true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -80,12 +74,31 @@ void AudioEffectModulatedDelay::set_modulator_filter_coeffs(void) |
|
|
|
|
// Example: https://web.fhnw.ch/technik/projekte/eit/Fruehling2016/MuelZum/html/parametric_equalizer_example_8c-example.html
|
|
|
|
|
// Coeeficients calculated with https://arachnoid.com/BiQuadDesigner/index.html
|
|
|
|
|
|
|
|
|
|
double frequency = 20.0; |
|
|
|
|
double q = 0.1; |
|
|
|
|
|
|
|
|
|
// low-pass
|
|
|
|
|
double w0 = frequency * (2 * M_PI / AUDIO_SAMPLE_RATE_EXACT); |
|
|
|
|
double sinW0 = sin(w0); |
|
|
|
|
double alpha = sinW0 / ((double)q * 2.0); |
|
|
|
|
double cosW0 = cos(w0); |
|
|
|
|
//double scale = 1073741824.0 / (1.0 + alpha); // for integers
|
|
|
|
|
double scale = 1.0 / (1.0 + alpha); |
|
|
|
|
|
|
|
|
|
modulator_filter_coeffs[0] = ((1.0 - cosW0) / 2.0) * scale; // b0
|
|
|
|
|
modulator_filter_coeffs[1] = (1.0 - cosW0) * scale; // b1
|
|
|
|
|
modulator_filter_coeffs[2] = modulator_filter_coeffs[0]; // b2
|
|
|
|
|
modulator_filter_coeffs[3] = (2.0 * cosW0) * scale; // -a1
|
|
|
|
|
modulator_filter_coeffs[4] = (-1.0 - alpha) * scale; // -a2
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// SR = 44110, Fc = 20 Hz; Q=0.707
|
|
|
|
|
modulator_filter_coeffs[0] = 5.06973332e-7; // b0
|
|
|
|
|
modulator_filter_coeffs[1] = 1.01394666e-6; // b1
|
|
|
|
|
modulator_filter_coeffs[2] = modulator_filter_coeffs[0]; // b2
|
|
|
|
|
modulator_filter_coeffs[3] = 1.99798478; // -a1
|
|
|
|
|
modulator_filter_coeffs[4] = -0.99798681; // -a2
|
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AudioEffectModulatedDelay::update(void) |
|
|
|
@ -135,14 +148,7 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
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));
|
|
|
|
|
*bp = (round(float(_delayline[cb_mod_index]) * mod_fraction + float(_delayline[cb_mod_index_neighbor]) * (1.0 - mod_fraction))+z1)/2; |
|
|
|
|
z1 = *bp; |
|
|
|
|
|
|
|
|
|
float bp_f = *bp / float(SHRT_MAX); |
|
|
|
|
lp->tick(&bp_f, 0.95f); |
|
|
|
|
*bp = round(bp_f * SHRT_MAX); |
|
|
|
|
*bp = dcFilter->next(*bp); |
|
|
|
|
*bp = round(float(_delayline[cb_mod_index]) * mod_fraction + float(_delayline[cb_mod_index_neighbor]) * (1.0 - mod_fraction)); |
|
|
|
|
|
|
|
|
|
// push the pointers forward
|
|
|
|
|
bp++; // next audio data
|
|
|
|
@ -163,13 +169,13 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
|
|
|
|
|
float AudioEffectModulatedDelay::offset(float offset_value) // in ms
|
|
|
|
|
{ |
|
|
|
|
uint16_t offset_frames = (offset_value / 1000) * AUDIO_SAMPLE_RATE; |
|
|
|
|
if (offset_frames > _delay_length * MODULATION_MAX_FACTOR) |
|
|
|
|
_delay_offset = _delay_length * MODULATION_MAX_FACTOR; |
|
|
|
|
else if (offset_frames <= _delay_length * (1 - MODULATION_MAX_FACTOR)) |
|
|
|
|
_delay_offset = _delay_length * (1 - MODULATION_MAX_FACTOR); |
|
|
|
|
uint16_t offset_frames = floor((offset_value / 1000) * AUDIO_SAMPLE_RATE); |
|
|
|
|
if (offset_frames > round( _delay_length * MODULATION_MAX_FACTOR)) |
|
|
|
|
_delay_offset = floor(_delay_length * MODULATION_MAX_FACTOR); |
|
|
|
|
else if (offset_frames <= round(_delay_length * (1 - MODULATION_MAX_FACTOR))) |
|
|
|
|
_delay_offset = floor(_delay_length * (1 - MODULATION_MAX_FACTOR)); |
|
|
|
|
else |
|
|
|
|
_delay_offset = offset_frames; |
|
|
|
|
|
|
|
|
|
return (offset_frames / AUDIO_SAMPLE_RATE * 1000); |
|
|
|
|
return (floor(offset_frames / AUDIO_SAMPLE_RATE * 1000)); |
|
|
|
|
} |
|
|
|
|