package dsp.filter.equalizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
import sample.complex.Complex;
public class CMAEqualizer implements Listener<Complex>
{
private final static Logger mLog = LoggerFactory.getLogger( CMAEqualizer.class );
public static final int TAP_COUNT = 11;
private float mModulus;
private float mMu;
private Complex mError = new Complex( 0.0f, 0.0f );
private Complex[] mTaps = new Complex[ TAP_COUNT ];
private Complex[] mBuffer = new Complex[ TAP_COUNT ];
private int mBufferPointer = 0;
private Listener<Complex> mListener;
public CMAEqualizer( float modulus, float mu )
{
mModulus = modulus;
mMu = mu;
/* Set first tap to 1,0 and all other taps to 0,0 as a starting point.
* This means that the output is solely determined by the last sample
* entering the filter, initially. */
mTaps[ 0 ] = new Complex( 1.0f, 0.0f );
for( int x = 1; x < TAP_COUNT; x++ )
{
mTaps[ x ] = new Complex( 0.0f, 0.0f );
mBuffer[ x ] = new Complex( 0.0f, 0.0f );
}
}
private void updateTaps( Complex sample )
{
/* Calculate the error. The ideal sample magnitude is unity (1.0).
* When the sample is not at unity, the error vector points in the
* opposite direction with a magnitude equal to 1 - sample magnitude.*/
mError = Complex.multiply( sample, sample.norm() - mModulus );
/* Ensure we don't exceed unity */
mError.clip( 1.0f );
for( int x = 0; x < TAP_COUNT; x++ )
{
// tap -= mu * conj(sample) * error
mTaps[ x ] = Complex.subtract( mTaps[ x ],
Complex.multiply( Complex.multiply(
mBuffer[ x ].conjugate(), mError ), mMu ) );
}
}
@Override
public void receive( Complex sample )
{
mBuffer[ mBufferPointer ] = sample;
mBufferPointer++;
mBufferPointer = mBufferPointer % TAP_COUNT;
Complex equalized = filter();
updateTaps( equalized );
if( mListener != null )
{
mListener.receive( equalized );
}
mLog.debug( "Tap 0:" + mTaps[ 0 ].toString() + " error:" + mError.toString() );
}
private Complex filter()
{
Complex sum = new Complex( 0.0f, 0.0f );
for( int x = 0; x < TAP_COUNT; x++ )
{
sum = Complex.add( sum, Complex.multiply(
mBuffer[ ( x + mBufferPointer ) % TAP_COUNT ],
mTaps[ TAP_COUNT - x - 1 ] ) );
}
return sum;
}
public void setListener( Listener<Complex> listener )
{
mListener = listener;
}
}