Инструменты пользователя

Инструменты сайта


math:calcrms

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;   
	}
};
math/calcrms.txt · Последнее изменение: 2023/06/21 12:49 — vasco