Code: Select all
class EnvelopeFollower
{
public:
EnvelopeFollower();
void Setup( double attackMs, double releaseMs, int sampleRate );
template<class T, int skip>
void Process( size_t count, const T *src );
template<class T>
void Process( T v );
double envelope;
protected:
double a;
double r;
};
inline EnvelopeFollower::EnvelopeFollower()
{
envelope=0;
}
inline void EnvelopeFollower::Setup( double attackMs, double releaseMs, int sampleRate )
{
a = pow( 0.01, 1.0 / ( attackMs * sampleRate * 0.001 ) );
r = pow( 0.01, 1.0 / ( releaseMs * sampleRate * 0.001 ) );
}
template<class T, int skip>
void EnvelopeFollower::Process( size_t count, const T *src )
{
double v;
while( count-- )
{
v=::fabs( *src );
if( v>envelope )
envelope = a * ( envelope - v ) + v;
else
envelope = r * ( envelope - v ) + v;
src+=skip;
}
}
template<class T>
void EnvelopeFollower::Process( T v )
{
v=::fabs( v );
if( v>envelope )
envelope = a * ( envelope - v ) + v;
else
envelope = r * ( envelope - v ) + v;
}
//-------
class OutputClipper
{
public:
OutputClipper();
template<class T, int skip>
void Process( size_t count, T *dest, const T *src );
EnvelopeFollower envelope;
bool bClipped;
};
inline OutputClipper::OutputClipper()
{
bClipped=false;
}
template<class T, int skip>
void OutputClipper::Process(
size_t count,
T *dest,
const T *src )
{
bClipped=false;
while( count-- )
{
if( *src>1 )
{
*dest=1;
bClipped=true;
}
else if( *src<-1 )
{
*dest=-1;
bClipped=true;
}
else
{
*dest=*src;
}
envelope.Process( *src );
src+=skip;
dest+=skip;
}
}
