//
//  Copyright (c) 2001, Reson, Inc. All Rights Reserved.
//
//  Filename:   EdgeTechChannelScale.cpp
//
//  Project:    6046.
//
//  Author(s):  W. Arcus
//
//  Purpose:    
//
//  Notes:

#include "stdafx.h"
#include "math.h"
#include "EdgeTechChannelScale.h"


CEdgeTechChannelScale::CEdgeTechChannelScale( const bool &rbEnable )
                      :m_fMaxRange( 32767.0f ),
                       m_iMaxPeriodResetValue( 999999 )
{
    m_bScaling = rbEnable;
    Reset();
}

CEdgeTechChannelScale::~CEdgeTechChannelScale( void )
{
    Reset();
}
/*
CEdgeTechChannelScale::CEdgeTechChannelScale( const CEdgeTechChannelScale &rRhs )
                      :m_fMaxRange( 32767.0f ),
                       m_iMaxPeriodResetValue( 999999 )
{
    m_bScaling          = rRhs.m_bScaling;

    m_iMaxWeightFactor  = rRhs.m_iMaxWeightFactor;
    m_iMaxPeriod        = rRhs.m_iMaxPeriod;
    m_iPingsThisPeriod  = rRhs.m_iPingsThisPeriod;
    m_fScaleBase        = rRhs.m_fScaleBase;
}
/*
CEdgeTechChannelScale::CEdgeTechChannelScale & operator = ( const CEdgeTechChannelScale &rRhs )
{
    m_bScaling          = rRhs.m_bScaling;

    m_iMaxWeightFactor  = rRhs.m_iMaxWeightFactor;
    m_iMaxPeriod        = rRhs.m_iMaxPeriod;
    m_iPingsThisPeriod  = rRhs.m_iPingsThisPeriod;
    m_fScaleBase        = rRhs.m_fScaleBase;

    return *this;
}
*/
void CEdgeTechChannelScale::ScaleChannelData    (   const short             &rnWeightFactor,
                                                    short                   *pnChannelData,
                                                    const unsigned long     &rulSamples )
{
    float fScaleFactor = ComputeScaleFactor( rnWeightFactor, pnChannelData, rulSamples );

    if ( m_bScaling )
    {
        float fValue;

        for ( unsigned long ulSample = 0UL; ulSample < rulSamples; ulSample++ )
        {
            fValue = ((float) pnChannelData[ ulSample ]) * fScaleFactor;

            if ( fValue < -m_fMaxRange )
            {
                fValue = -m_fMaxRange;
            }

            if ( fValue > m_fMaxRange )
            {
                fValue = m_fMaxRange;
            }

            pnChannelData[ ulSample ] = (short) fValue;
        }
    }
}

void CEdgeTechChannelScale::EnableScaling( const bool &rbEnable )
{
    m_bScaling = rbEnable;
}

void CEdgeTechChannelScale::Reset ( void )
{
    m_iMaxWeightFactor  = m_iMaxPeriodResetValue;
    m_iMaxPeriod        = m_iMaxPeriodResetValue;
    m_iPingsThisPeriod  = 0;
    m_fScaleBase        = 1.0f;
}

float CEdgeTechChannelScale::ComputeScaleFactor(    const short            &rnWeightFactor,
                                                    const short            *pnChannelData,
                                                    const unsigned long    &rulSamples )
{
    float   fScale = 1.0f;
    int     iWeight = (int) rnWeightFactor;

    if ( m_bScaling )
    {
        m_fScaleBase = 1.0;

        if ( iWeight < m_iMaxWeightFactor )
        {
            m_iMaxWeightFactor = iWeight;
        }

        if ( iWeight < m_iMaxPeriod )
        {
            m_iMaxPeriod = iWeight;
        }

        if ( m_iPingsThisPeriod++ > 100 )
        {
            m_iPingsThisPeriod = 0;

            if ( m_iMaxPeriod - m_iMaxWeightFactor >= 5 ) // More than 4 bits lost
            {
                m_iMaxWeightFactor = m_iMaxPeriod;
            }

            m_iMaxPeriod = m_iMaxPeriodResetValue;
        }

        fScale = m_fScaleBase * (float) pow( 2.0, (double) (m_iMaxWeightFactor - iWeight) );
    }
    else
    {
        m_iMaxWeightFactor = iWeight;
        m_fScaleBase = 1.0;
        return fScale;
    }

    return fScale;
}


  
