52 lines
1.7 KiB
C++
52 lines
1.7 KiB
C++
#include "resampler.h"
|
|
using namespace Xybrid::NodeLib;
|
|
|
|
|
|
#include <iostream>
|
|
#include <array>
|
|
#ifdef WITH_BOOST
|
|
#include <boost/math/special_functions/bessel.hpp>
|
|
#else
|
|
#include <cmath>
|
|
#endif
|
|
namespace {
|
|
const constexpr double PI = 3.141592653589793238462643383279502884197169399375105820974;
|
|
|
|
const constexpr double KAISER_ALPHA = 7.5;
|
|
const constexpr double KAISER_BETA = PI * KAISER_ALPHA;
|
|
|
|
inline constexpr double sinc(double x) {
|
|
if (x == 0) return 1;
|
|
double px = x * PI;
|
|
return std::sin(px) / px;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// generate
|
|
const std::array<std::array<double, LUT_TAPS>, LUT_STEPS> Xybrid::NodeLib::resamplerLUT = [] {
|
|
#ifdef WITH_BOOST
|
|
double denom = boost::math::cyl_bessel_i(0, KAISER_BETA);
|
|
#else
|
|
double denom = std::cyl_bessel_i(0, KAISER_BETA);
|
|
#endif
|
|
std::array<std::array<double, LUT_TAPS>, LUT_STEPS> t;
|
|
t[0] = {0, 0, 0, 1, 0, 0, 0, 0}; // we already know the ideal integer step
|
|
for (size_t step = 1; step < LUT_STEPS; step++) {
|
|
double sv = static_cast<double>(step) / LUT_STEPS;
|
|
for (size_t tap = 0; tap < LUT_TAPS; tap++) {
|
|
double x = static_cast<double>(tap) - sv;
|
|
#ifdef WITH_BOOST
|
|
t[step][tap] = sinc(x-(LUT_TAPS/2-1)) * (boost::math::cyl_bessel_i(0, KAISER_BETA * std::sqrt(1 - std::pow(((2 * (x+1)) / (LUT_TAPS)) - 1, 2))) / denom);
|
|
#else
|
|
t[step][tap] = sinc(x-(LUT_TAPS/2-1)) * (std::cyl_bessel_i(0, KAISER_BETA * std::sqrt(1 - std::pow(((2 * (x+1)) / (LUT_TAPS)) - 1, 2))) / denom);
|
|
#endif
|
|
if (t[step][tap] != t[step][tap]) t[step][tap] = 0; // NaN guard
|
|
//std::cout << "tap " << tap << ": " << t[step][tap] << " ";
|
|
}
|
|
//std::cout << "\n";
|
|
}
|
|
return t;
|
|
}();
|