219 lines
5.6 KiB
C++
219 lines
5.6 KiB
C++
#ifndef MMATH_INTERPOLATE_H
|
|
#define MMATH_INTERPOLATE_H
|
|
#include <cmath>
|
|
|
|
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 <typename T>
|
|
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 <typename T>
|
|
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 <typename T>
|
|
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 <typename T>
|
|
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 <typename T>
|
|
Linear<T>::Linear(const T & y1, const T & y2) : v1(y1), v2(y2) {}
|
|
|
|
template <typename T>
|
|
T Linear<T>::getAt(const T & mu) const {
|
|
return v1 * (1 - mu) + v2 * mu;
|
|
}
|
|
|
|
template <typename T>
|
|
void Linear<T>::shiftAndFeed(const T & y_i) {
|
|
v1 = v2;
|
|
v2 = y_i;
|
|
}
|
|
|
|
// Cubic
|
|
|
|
template <typename T>
|
|
Cubic<T>::Cubic(const T & y0,
|
|
const T & y1, const T & y2, const T & y3) {
|
|
setCoefficients(y0, y1, y2, y3);
|
|
}
|
|
|
|
template <typename T>
|
|
Cubic<T>::Cubic(const T & y1,
|
|
const T & y2, const T & y3) {
|
|
setCoefficients(2 * y1 - y2, y1, y2, y3);
|
|
}
|
|
|
|
template <typename T>
|
|
void Cubic<T>::shiftAndFeed(const T & y_i) {
|
|
setCoefficients(a3, v2, v3, y_i);
|
|
}
|
|
|
|
template <typename T>
|
|
void Cubic<T>::shift() {
|
|
setCoefficients(a3, v2, v3, 2 * v2 - a3);
|
|
}
|
|
|
|
template <typename T>
|
|
void Cubic<T>::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 <typename T>
|
|
T Cubic<T>::getAt(const T & mu) const {
|
|
const T mu_sq = mu * mu;
|
|
return(a0 * mu * mu_sq + a1 * mu_sq + a2 * mu + a3);
|
|
}
|
|
|
|
// Cosine
|
|
|
|
template <typename T>
|
|
Cosine<T>::Cosine(const T & y1, const T & y2) : v1(y1), v2(y2) {}
|
|
|
|
template <typename T>
|
|
T Cosine<T>::getAt(const T & mu) const {
|
|
T mu2 = (1 - cos(mu * M_PI)) / 2;
|
|
return v1 * (1 - mu2) + v2 * mu2;
|
|
}
|
|
|
|
template <typename T>
|
|
void Cosine<T>::shiftAndFeed(const T & y_i) {
|
|
v1 = v2;
|
|
v2 = y_i;
|
|
}
|
|
|
|
// Hermite
|
|
|
|
template <typename T>
|
|
Hermite<T>::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 <typename T>
|
|
T Hermite<T>::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 <typename T>
|
|
void Hermite<T>::setCoefficients(const T y0, const T y1, const T y2,
|
|
const T y3) {
|
|
v0 = y0; v1 = y1; v2 = y2; v3 = y3;
|
|
updateCoefficients();
|
|
}
|
|
|
|
template <typename T>
|
|
void Hermite<T>::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 <typename T>
|
|
void Hermite<T>::setTension(const T & _tension) {
|
|
tension = _tension;
|
|
updateCoefficients();
|
|
}
|
|
|
|
template <typename T>
|
|
void Hermite<T>::setBias(const T & _bias) {
|
|
bias = _bias;
|
|
updateCoefficients();
|
|
}
|
|
|
|
template <typename T>
|
|
void Hermite<T>::shiftAndFeed(const T & y_i) {
|
|
setCoefficients(v1, v2, v3, y_i);
|
|
}
|
|
|
|
template <typename T>
|
|
void Hermite<T>::shift() {
|
|
setCoefficients(v1, v2, v3, 2 * v2 - v1);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|