RMS Calculation
Listing 1. C++ class that computes the root-mean using Newton's Method for the reciprocal square root
static const double Fs = 48000.0; // sample rate
static double AvgTime = 0.1; // averaging time
class RecipRootMean{
public:
double Mean;
double RecipRootMean;
double AvgCoeff;
RecipRootMean()
{
AvgCoeff = 1.0 - exp( -1.0 / (Fs * AvgTime) );
Mean = 0.0;
RecipRootMean = 1.0e-10; // 1 > initial RecipRootMean > 0
}
~RecipRootMean() {}
double CalcRootMean(double x)
{
Mean += AvgCoeff * (x - Mean);
RecipRootMean *= 0.5 * ( 3.0 - (RecipRootMean * RecipRootMean * Mean) );
return RecipRootMean * Mean;
}
};
Mean-square computation that combines averaging and iterative square root
Listing 2. C++ class that implements the floating-point version
static const double Fs = 48000.0; // sample rate
static double AvgTime = 0.1; // averaging time
class NewtonRootMean{
public:
double RootMean;
double AvgCoeff;
NewtonRootMean()
{
RootMean = 1.0; // > 0 or divide will fail
AvgCoeff = 0.5 * ( 1.0 - exp( -1.0 / (Fs * AvgTime) ) );
}
~NewtonRootMean() {}
double CalcRootMean(double x)
{
RootMean += AvgCoeff * ( ( x / RootMean ) - RootMean );
return RootMean;
}
};
Listing 3. C++ class that implements the fixed-point version
static const double Fs = 48000.0; // sample rate
static double AvgTime = 0.1; // averaging time
static const unsigned int sknNumIntBits = 32;
// # bits in int
static const unsigned int sknPrecisionBits = sknNumIntBits / 2;
static const double skScaleFactor = pow(2.0, (double)sknPrecisionBits);
static const unsigned int sknRoundOffset = (unsigned int)floor( 0.5 * skScaleFactor );
class IntNewtonRootMean{
public:
unsigned int nRootMean;
unsigned int nScaledRootMean;
unsigned int nAvgCoeff;
unsigned int nMaxVal;
IntNewtonRootMean()
{
nRootMean = 1; // >0 or divide will fail
nScaledRootMean = 0;
double AvgCoeff = 0.5 * ( 1.0 - exp( -1.0 / (Fs * AvgTime) ) );
nAvgCoeff = (unsigned int)floor( ( skScaleFactor * AvgCoeff ) + 0.5 );
nMaxVal = (unsigned int)floor( ( skScaleFactor / AvgCoeff ) + 0.5 );
}
~IntNewtonRootMean() {}
unsigned int CalcRootMean(unsigned int x)
{
if ( x < nMaxVal)
{
nScaledRootMean += ((nAvgCoeff * x) / nRootMean ) - (nAvgCoeff * nRootMean);
} else {
nScaledRootMean += nAvgCoeff * (( x / nRootMean ) - nRootMean );
}
nRootMean = ( nScaledRootMean + sknRoundOffset ) >> sknPrecisionBits;
return nRootMean;
}
};