Replaced own filter functions with CMSIS library function calls.

master
Holger Wirtz 5 years ago
parent 807d152020
commit cd891c4f98
  1. 5
      config.h
  2. 131
      effect_modulated_delay.cpp
  3. 11
      effect_modulated_delay.h

@ -56,9 +56,8 @@
#define REDUCE_LOUDNESS 0 #define REDUCE_LOUDNESS 0
#define USE_XFADE_DATA 1 #define USE_XFADE_DATA 1
// CHORUS parameters // CHORUS parameters
#define INTERPOLATION_WINDOW_SIZE 7 // use only odd numbers!!! #define INTERPOLATION_WINDOW_SIZE 5 // use only odd numbers!!!
#define INTERPOLATE_MODE 11 //#define INTERPOLATE_MODE 11
#define FILTER_IIR_ORDER_3 1
#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_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!

@ -58,6 +58,12 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length)
_delayline = delayline; _delayline = delayline;
_delay_length = _max_delay_length = d_length; _delay_length = _max_delay_length = d_length;
// init filter
filter.numStages = 1;
filter.pState = filter_state;
filter.pCoeffs = filter_coeffs;
calcModFilterCoeff(5000.0, 0.0, 5.0);
return (true); return (true);
} }
@ -66,31 +72,33 @@ void AudioEffectModulatedDelay::update(void)
audio_block_t *block; audio_block_t *block;
audio_block_t *modulation; audio_block_t *modulation;
int16_t *bp;
int16_t *mp;
float mod_idx;
if (_delayline == NULL) if (_delayline == NULL)
return; return;
block = receiveWritable(0); block = receiveWritable(0);
modulation = receiveReadOnly(1); modulation = receiveReadOnly(1);
#ifdef INTERPOLATE_MODE
int8_t j;
float x[INTERPOLATION_WINDOW_SIZE];
float y[INTERPOLATION_WINDOW_SIZE];
Spline s(x, y, INTERPOLATION_WINDOW_SIZE, INTERPOLATE_MODE);
#endif
bp = block->data;
mp = modulation->data;
if (block && modulation) if (block && modulation)
{ {
int16_t *bp;
float *mp;
float mod_idx;
float mod_number; float mod_number;
float mod_fraction; float mod_fraction;
#ifdef INTERPOLATE_MODE
int8_t j;
float x[INTERPOLATION_WINDOW_SIZE];
float y[INTERPOLATION_WINDOW_SIZE];
Spline s(x, y, INTERPOLATION_WINDOW_SIZE, INTERPOLATE_MODE);
#endif
// (Filter implementation: https://web.fhnw.ch/technik/projekte/eit/Fruehling2016/MuelZum/html/parametric__equalizer__example_8c_source.html)
arm_q15_to_float(modulation->data, modulation_f32, AUDIO_BLOCK_SAMPLES);
arm_biquad_cascade_df1_f32(&filter, modulation_f32, modulation_f32, AUDIO_BLOCK_SAMPLES);
bp = block->data;
mp = modulation_f32;
for (uint16_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) for (uint16_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
{ {
// write data into circular buffer // write data into circular buffer
@ -100,56 +108,7 @@ void AudioEffectModulatedDelay::update(void)
// Calculate modulation index as a float, for interpolation later. // Calculate modulation index as a float, for interpolation later.
// 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 = *mp * float(_delay_length >> 1);
Use an IIR filter on the modulation for avoiding aliasing (http://www-users.cs.york.ac.uk/~fisher/mkfilter/) */
#if defined(FILTER_IIR_ORDER_1)
/* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
Command line: /www/usr/fisher/helpers/mkfilter -Bu -Lp -o 1 -a 1.1333499558e-01 0.0000000000e+00 -l
Parameters: filtertype = Butterworth
passtype = Lowpass
ripple =
order = 1
samplerate = 44117.64706
corner1 = 5000
corner2 =
adzero =
logmin =
**************************************************************************************************************/
#define NZEROS 1
#define NPOLES 1
#define GAIN 3.688918967e+00
static float xv[NZEROS + 1], yv[NPOLES + 1];
xv[0] = xv[1];
xv[1] = (float(*mp) / SHRT_MAX) / GAIN;
yv[0] = yv[1];
yv[1] = (xv[0] + xv[1]) + (0.4578357460 * yv[0]);
//new_value = yv[1];
mod_idx = yv[1] * float(_delay_length >> 1);
#elif defined(FILTER_IIR_ORDER_3)
/* Digital filter designed by mkfilter/mkshape/gencode A.J. Fisher
Command line: /www/usr/fisher/helpers/mkfilter -Bu -Lp -o 3 -a 1.1333333333e-01 0.0000000000e+00 -l
raw alpha1 = 0.1133333333
raw alpha2 = 0.1133333333
warped alpha1 = 0.1183783855
warped alpha2 = 0.1183783855
gain at dc : mag = 4.028005941e+01 phase = 0.0000000000 pi
gain at centre: mag = 2.848230315e+01 phase = -0.7500000000 pi
gain at hf : mag = 0.000000000e+00
**************************************************************************************************************/
#define NZEROS 3
#define NPOLES 3
#define GAIN 4.028005941e+01
static float xv[NZEROS + 1], yv[NPOLES + 1];
xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3];
xv[3] = (float(*mp) / SHRT_MAX) / GAIN;
yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3];
yv[3] = (xv[0] + xv[3]) + 3 * (xv[1] + xv[2])
+ ( 0.2323461955 * yv[0]) + ( -1.0299524229 * yv[1])
+ ( 1.5989967885 * yv[2]);
//new_value = yv[3];
mod_idx = yv[3] * float(_delay_length >> 1);
/************************************************************************/
#endif
mod_fraction = modff(mod_idx, &mod_number); mod_fraction = modff(mod_idx, &mod_number);
#ifdef INTERPOLATE_MODE #ifdef INTERPOLATE_MODE
@ -173,13 +132,13 @@ void AudioEffectModulatedDelay::update(void)
if (c_mod_idx < 0) if (c_mod_idx < 0)
{ {
value1 = _delayline[_delay_length + c_mod_idx]; value1 = _delayline[_delay_length + c_mod_idx - 1];
value2 = _delayline[_delay_length + c_mod_idx - 1]; value2 = _delayline[_delay_length + c_mod_idx];
} }
else else
{ {
value1 = _delayline[c_mod_idx]; value1 = _delayline[c_mod_idx - 1];
value2 = _delayline[c_mod_idx - 1]; value2 = _delayline[c_mod_idx];
} }
*bp = mod_fraction * value1 + (1.0 - mod_fraction) * value2; *bp = mod_fraction * value1 + (1.0 - mod_fraction) * value2;
#endif #endif
@ -190,17 +149,47 @@ void AudioEffectModulatedDelay::update(void)
} }
} }
if (modulation)
release(modulation);
if (block) if (block)
{ {
transmit(block, 0); transmit(block, 0);
release(block); release(block);
} }
if (modulation)
release(modulation);
} }
void AudioEffectModulatedDelay::setDelay(float milliseconds) void AudioEffectModulatedDelay::setDelay(float milliseconds)
{ {
_delay_length = min(AUDIO_SAMPLE_RATE * milliseconds / 500, _max_delay_length); _delay_length = min(AUDIO_SAMPLE_RATE * milliseconds / 500, _max_delay_length);
} }
void AudioEffectModulatedDelay::calcModFilterCoeff(float32_t cFrq, float32_t gain, float32_t width)
{
/* Calculate intermediate values */
float32_t A = sqrt(pow(10, gain / 20.0f));
float32_t w0 = 2.0f * PI * cFrq / ((float32_t)AUDIO_SAMPLE_RATE_EXACT);
float32_t cosw0 = cos(w0);
float32_t sinw0 = sin(w0);
float32_t alpha = sinw0 / (2.0f * width);
/* Calculate coefficients */
float32_t b0 = 1.0f + alpha * A;
float32_t b1 = -2.0f * cosw0;
float32_t b2 = 1.0f - alpha * A;
float32_t a0 = 1.0f + alpha / A;
float32_t a1 = -2.0f * cosw0;
float32_t a2 = 1.0f - alpha / A;
/* Normalize so a0 = 1 */
filter_coeffs[0] = b0 / a0;
filter_coeffs[1] = b1 / a0;
filter_coeffs[2] = b2 / a0;
filter_coeffs[3] = -a1 / a0;
filter_coeffs[4] = -a2 / a0;
}
void AudioEffectModulatedDelay::setModFilter(float cFrq, float gain, float width)
{
calcModFilterCoeff(cFrq, gain, width);
}

@ -34,9 +34,6 @@
// 140219 - correct storage class (not static) // 140219 - correct storage class (not static)
// 190527 - added modulation input handling (by Holger Wirtz) // 190527 - added modulation input handling (by Holger Wirtz)
#define MODF(n,i,f) ((i) = (int)(n), (f) = (n) - (double)(i))
class AudioEffectModulatedDelay : class AudioEffectModulatedDelay :
public AudioStream public AudioStream
{ {
@ -48,13 +45,21 @@ class AudioEffectModulatedDelay :
boolean begin(short *delayline, int delay_length); boolean begin(short *delayline, int delay_length);
virtual void update(void); virtual void update(void);
virtual void setDelay(float milliseconds); virtual void setDelay(float milliseconds);
virtual void setModFilter(float cFrq, float gain, float width);
private: private:
virtual void calcModFilterCoeff(float32_t cFrq, float32_t gain, float32_t width);
audio_block_t *inputQueueArray[2]; audio_block_t *inputQueueArray[2];
int16_t *_delayline; int16_t *_delayline;
uint16_t _circ_idx; uint16_t _circ_idx;
uint16_t _max_delay_length; uint16_t _max_delay_length;
uint16_t _delay_length; uint16_t _delay_length;
// filter data
arm_biquad_casd_df1_inst_f32 filter;
float32_t modulation_f32[AUDIO_BLOCK_SAMPLES];
float32_t filter_coeffs[5];
float32_t filter_state[4];
}; };
#endif #endif

Loading…
Cancel
Save