| 
							- #pragma once
 - template <typename T, int order>
 - class Poly
 - {
 - public:
 -     Poly();
 -     float run(float x, float inputGain);
 -     void setGain(int index, float value)
 -     {
 -         assert(index >= 0 && index < order);
 -         gains[index] = value;
 -     }
 - 
 -     T getOutput(int index) const
 -     {
 -         return outputs[index];
 -     }
 - 
 - private:
 -     T gains[order];
 - 
 -     // powers[0] = x, powers[1] = x**2
 -     T powers[order];
 - 
 -     T outputs[order];
 - 
 -     // since DC offset changes with gain, we need to compute it.
 -     static const int numEvenHarmonics = order / 2;
 -     T dcComponent[numEvenHarmonics];
 - 
 -     void fillPowers(T);
 -     T doSum();
 -     void calcDC(T gain);
 - };
 - 
 - template <typename T, int order>
 - inline Poly<T, order>::Poly()
 - {
 -     assert(order == 10);        // Although this class it templated, internally it's hard coded.
 -     for (int i = 0; i < order; ++i) {
 -         gains[i] = 0;
 -         powers[i] = 0;
 -         outputs[i] = 0;
 -     }
 - 
 -     for (int i = 0; i < numEvenHarmonics; ++i) {
 -         dcComponent[i] = 0;
 -     }
 - }
 - 
 - template <typename T, int order>
 - inline float Poly<T, order>::run(float x, float inputGain)
 - {
 -     fillPowers(x);
 -     calcDC(inputGain);
 -     return (float) doSum();
 - }
 - 
 - template <typename T, int order>
 - inline void Poly<T, order>::fillPowers(T x)
 - {
 -     T value = x;
 -     for (int i = 0; i < order; ++i) {
 -         powers[i] = value;
 -         value *= x;
 -     }
 - }
 - 
 - template <typename T, int order>
 - inline T Poly<T, order>::doSum()
 - {
 -     outputs[0] =  powers[0];
 -     T sum = outputs[0] * gains[0];
 - 
 -     outputs[1] = (2 * powers[1] - dcComponent[0]);
 -     sum += outputs[1] * gains[1];
 - 
 -     outputs[2] =  (4 * powers[2] - 3 * powers[0]);
 -     sum += outputs[2] * gains[2];
 - 
 -     outputs[3] =  (8 * powers[3] - 8 * powers[1] - dcComponent[1]);
 -     sum += outputs[3] * gains[3];
 - 
 -     outputs[4] =  (16 * powers[4] - 20 * powers[2] + 5 * powers[0]);
 -     sum += outputs[4] * gains[4];
 - 
 -     outputs[5] =  (32 * powers[5] - 48 * powers[3] + 18 * powers[1] - dcComponent[2]);
 -     sum += outputs[5] * gains[5];
 - 
 -     outputs[6] =  (64 * powers[6] - 112 * powers[4] + 56 * powers[2] - 7 * powers[0]);
 -     sum += outputs[6] * gains[6];
 - 
 -     outputs[7] =  (128 * powers[7] - 256 * powers[5] + 160 * powers[3] - 32 * powers[1] - dcComponent[3]);
 -     sum += outputs[7] * gains[7];
 - 
 -     outputs[8] =  (256 * powers[8] - 576 * powers[6] + 432 * powers[4] - 120 * powers[2] + 9 * powers[0]);
 -     sum += outputs[8] * gains[8];
 - 
 -     outputs[9] =  (512 * powers[9] - 1280 * powers[7] + 1120 * powers[5] - 400 * powers[3] + 50 * powers[1] - dcComponent[4]);
 -     sum += outputs[9] * gains[9];
 - 
 -     return sum;
 - }
 - #if 0 // old way
 - template <typename T, int order>
 - inline T Poly<T, order>::doSum()
 - {
 -     T ret = gains[0] * powers[0];
 -     ret += gains[1] * (2 * powers[1] - dcComponent[0]);
 -     ret += gains[2] * (4 * powers[2] - 3 * powers[0]);
 -     ret += gains[3] * (8 * powers[3] - 8 * powers[1] - dcComponent[1]);
 -     ret += gains[4] * (16 * powers[4] - 20 * powers[2] + 5 * powers[0]);
 -     ret += gains[5] * (32 * powers[5] - 48 * powers[3] + 18 * powers[1] - dcComponent[2]);
 -     ret += gains[6] * (64 * powers[6] - 112 * powers[4] + 56 * powers[2] - 7 * powers[0]);
 -     ret += gains[7] * (128 * powers[7] - 256 * powers[5] + 160 * powers[3] - 32 * powers[1] - dcComponent[3]);
 -     ret += gains[8] * (256 * powers[8] - 576 * powers[6] + 432 * powers[4] - 120 * powers[2] + 9 * powers[0]);
 -     ret += gains[9] * (512 * powers[9] - 1280 * powers[7] + 1120 * powers[5] - 400 * powers[3] + 50 * powers[1] - dcComponent[4]);
 -     return ret;
 - }
 - #endif
 - 
 - template <typename T, int order>
 - void Poly<T, order>::calcDC(T gain)
 - {
 -     // first calculate "sinEnergy", which is the integral of sin^n(gain * x) over a period
 -     const double W2 = 2.0 / 4.0;
 -     const double W4 = W2 * 3.0 / 4.0;
 -     const double W6 = W4 * 5.0 / 6.0;
 -     const double W8 = W6 * 7.0 / 8.0;
 -     const double W10 = W8 * 9.0 / 10.0;
 - 
 -     T sinEnergy = gain;
 -     T sinEnergy2 = sinEnergy * sinEnergy;
 -     T sinEnergy4 = sinEnergy2 * sinEnergy2;
 -     T sinEnergy6 = sinEnergy4 * sinEnergy2;
 -     T sinEnergy8 = sinEnergy6 * sinEnergy2;
 -     T sinEnergy10 = sinEnergy8 * sinEnergy2;
 - 
 -     sinEnergy2 *= W2;
 -     sinEnergy4 *= W4;
 -     sinEnergy6 *= W6;
 -     sinEnergy8 *= W8;
 -     sinEnergy10 *= W10;
 - 
 -     // for harmonic 1 (first even)
 -     dcComponent[0] = T(2 * sinEnergy2);
 -     dcComponent[1] = T(8 * sinEnergy4 - 8 * sinEnergy2);
 -     dcComponent[2] = T(32 * sinEnergy6 - 48 * sinEnergy4 + 18 * sinEnergy2);
 -     dcComponent[3] = T(128 * sinEnergy8 - 256 * sinEnergy6 + 160 * sinEnergy4  - 32 * sinEnergy2);
 -     dcComponent[4] = T(512 * sinEnergy10 - 1280 * sinEnergy8 + 1120 * sinEnergy6 - 400 * sinEnergy4 + 50 * sinEnergy2);
 - }
 
 
  |