Ok so I managed to write an envelope follower class, based on this:
http://sam-koblenski.blogspot.com/2015/10/everyday-dsp-for-programmers-signal.html
#ifndef ENV_FOLLOW_H
#define ENV_FOLLOW_H
#include <math.h>
namespace daisysp
{
class EnvFollow
{
private:
float avg; //exp average of input
float pos_sample; //positive sample
float sample_noDC; //no DC sample
float avg_env; //average envelope
float w; //weighting
float w_env; //envelope weighting
public:
EnvFollow() //default constructor
{
avg = 0.0f; //exp average of input
pos_sample = 0.0f; //positive sample
avg_env = 0.0f; //average envelope
w = 0.0001f; //weighting
w_env = 0.0001f; //envelope weighting
sample_noDC = 0.0f;
}
~EnvFollow() {}
float GetEnv(float sample)
{
//remove average DC offset:
avg = (w * sample) + ((1-w) * avg);
sample_noDC = sample - avg;
//take absolute
pos_sample = fabsf(sample_noDC);
//remove ripple
avg_env = (w_env * pos_sample) + ((1-w_env) * avg_env);
return avg_env;
}
};
} // namespace daisysp
#endif
This works pretty well, perhaps I could tweak the weighting values a little to improve the response, but it’s not bad. I then output this on the Daisy DAC, so I could view it on my scope as a DC voltage. I noticed that the range of my envelope follower float doesn’t go much above a value of 1.0. I know this won’t pick up all the peaks as it is averaging the signal, but shouldn’t this be in the ballpark of the magnitude of the audio signal? I was surprised, because I assumed the floats would have a maximum value of around 3 *10^38!
Anyhow, I managed to implement an inverse feedback using the envelope follower signal, and this works, managing the runaway feedback effectively. However if I put a really hot input signal in I can still get the audio to cutout.
What would the best way to hard limit the audio signal? I tried this:
out[i] = (mixL > HardLimit) ? HardLimit : mixL;
But still the audio cuts out. I used a value of 0.7f for the HardLimit.
Any tips would be much appreciated!