Output clipper with envelope follower (C++)

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Here's a pair of classes to perform output clipping and envelope detection, suitable for a VU meter. It illustrates the use of templates for supporting both double and float sample types using the same code. Additionally, the "skip" template argument allows the class to be used for interleaved stereo data (skip=2) or mono (skip=1)

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;
	}
}


Post

Nice example :)

Post Reply

Return to “DSP and Plugin Development”