#ifndef MMATH_INTERPOLATE_H #define MMATH_INTERPOLATE_H #include namespace Math { namespace Interpolator { /** Interpolate between values - creating data out of nothing. * * The math mainly comes from: * http://local.wasp.uwa.edu.au/~pbourke/other/interpolation/ * * Capsuled into classes which store the values to allow usage * as a kind of data - consumer/producer. * * This idea comes from here: */ // http://exult.cvs.sourceforge.net/*checkout*/exult/exult/audio/Audio.cc template class Linear { public: Linear(const T & y1, const T & y2); T getAt(const T & mu) const; void shiftAndFeed(const T & y_i); private: T v1, v2; }; template class Cubic { public: Cubic(const T & y0, const T & y1, const T & y2, const T & y3); Cubic(const T & y1, const T & y2, const T & y3); void shiftAndFeed(const T & y_i); void shift(); T getAt(const T & mu) const; private: void setCoefficients(const T y0, const T y1, const T y2, const T y3); T a0, a1, a2, a3; T v2, v3; }; template class Cosine { public: Cosine(const T & y1, const T & y2); T getAt(const T & mu) const; void shiftAndFeed(const T & y_i); private: T v1, v2; }; template class Hermite { public: Hermite(const T & y1, const T & y2, const T & y3, const T & _tension, const T & _bias); Hermite(const T & y0, const T & y1, const T & y2, const T & y3, const T & _tension, const T & _bias); T getAt(const T & mu) const; void shiftAndFeed(const T & y_i); void shift(); void setTension(const T & _tension); void setBias(const T & _bias); private: void setCoefficients(const T y0, const T y1, const T y2, const T y3); void updateCoefficients(); T m0, m1; T v0, v1, v2, v3; T tension, bias; }; // implementation template Linear::Linear(const T & y1, const T & y2) : v1(y1), v2(y2) {} template T Linear::getAt(const T & mu) const { return v1 * (1 - mu) + v2 * mu; } template void Linear::shiftAndFeed(const T & y_i) { v1 = v2; v2 = y_i; } // Cubic template Cubic::Cubic(const T & y0, const T & y1, const T & y2, const T & y3) { setCoefficients(y0, y1, y2, y3); } template Cubic::Cubic(const T & y1, const T & y2, const T & y3) { setCoefficients(2 * y1 - y2, y1, y2, y3); } template void Cubic::shiftAndFeed(const T & y_i) { setCoefficients(a3, v2, v3, y_i); } template void Cubic::shift() { setCoefficients(a3, v2, v3, 2 * v2 - a3); } template void Cubic::setCoefficients(const T y0, const T y1, const T y2, const T y3) { v2 = y2; v3 = y3; a0 = y3 - y2 - y0 + y1; a1 = y0 - y1 - a0; a2 = y2 - y0; a3 = y1; } template T Cubic::getAt(const T & mu) const { const T mu_sq = mu * mu; return(a0 * mu * mu_sq + a1 * mu_sq + a2 * mu + a3); } // Cosine template Cosine::Cosine(const T & y1, const T & y2) : v1(y1), v2(y2) {} template T Cosine::getAt(const T & mu) const { T mu2 = (1 - cos(mu * M_PI)) / 2; return v1 * (1 - mu2) + v2 * mu2; } template void Cosine::shiftAndFeed(const T & y_i) { v1 = v2; v2 = y_i; } // Hermite template Hermite::Hermite(const T & y1, const T & y2, const T & y3, const T & _tension, const T & _bias) : tension(_tension), bias(_bias) { setCoefficients(2 * y1 - y2, y1, y2, y3); } template T Hermite::getAt(const T & mu) const { const T mu_sq = mu * mu; const T mu_cu = mu_sq * mu; T a0 = 2 * mu_cu - 3 * mu_sq + 1; T a1 = mu_cu - 2 * mu_sq + mu; T a2 = mu_cu - mu_sq; T a3 =-2 * mu_cu + 3 * mu_sq; return a0 * v1 + a1 * m0 + a2 * m1 + a3 * v2; } template void Hermite::setCoefficients(const T y0, const T y1, const T y2, const T y3) { v0 = y0; v1 = y1; v2 = y2; v3 = y3; updateCoefficients(); } template void Hermite::updateCoefficients() { m0 = (v1 - v0) * (1 + bias) * (1 - tension) / 2; m0 += (v2 - v1) * (1 - bias) * (1 - tension) / 2; m1 = (v2 - v1) * (1 + bias) * (1 - tension) / 2; m1 += (v3 - v2) * (1 - bias) * (1 - tension) / 2; } template void Hermite::setTension(const T & _tension) { tension = _tension; updateCoefficients(); } template void Hermite::setBias(const T & _bias) { bias = _bias; updateCoefficients(); } template void Hermite::shiftAndFeed(const T & y_i) { setCoefficients(v1, v2, v3, y_i); } template void Hermite::shift() { setCoefficients(v1, v2, v3, 2 * v2 - v1); } } } #endif