Clean up some includes
[openal-soft.git] / core / cubic_tables.cpp
blob0d6e513b8c8bf4912166dd990988085d1ed55778
2 #include "cubic_tables.h"
4 #include <array>
5 #include <cmath>
6 #include <cstddef>
8 #include "alnumbers.h"
9 #include "cubic_defs.h"
11 /* These filter tables are inspired by the gaussian-like filter found in the
12 * SNES. This is based on the public domain code developed by Near, with the
13 * help of Ryphecha and nocash, from the nesdev.org forums.
15 * <https://forums.nesdev.org/viewtopic.php?p=251534#p251534>
17 * Additional changes were made here, the most obvious being that is has full
18 * floating-point precision instead of 11-bit fixed-point, but also an offset
19 * adjustment for the phase coefficients to more cleanly transition from the
20 * end of one sample set to the start of the next.
22 namespace {
24 [[nodiscard]]
25 auto GetCoeff(double idx) noexcept -> double
27 const double k{0.5 + idx};
28 if(k > 512.0) return 0.0;
29 const double s{ std::sin(al::numbers::pi*1.280/1024 * k)};
30 const double t{(std::cos(al::numbers::pi*2.000/1023 * k) - 1.0) * 0.50};
31 const double u{(std::cos(al::numbers::pi*4.000/1023 * k) - 1.0) * 0.08};
32 return s * (t + u + 1.0) / k;
35 struct GaussFilterArray {
36 alignas(16) std::array<CubicCoefficients,CubicPhaseCount> mTable{};
38 GaussFilterArray()
40 static constexpr double IndexScale{512.0 / double{CubicPhaseCount*2}};
41 /* Fill in the main coefficients. */
42 for(std::size_t pi{0};pi < CubicPhaseCount;++pi)
44 const double coeff0{GetCoeff(static_cast<double>(CubicPhaseCount + pi)*IndexScale)};
45 const double coeff1{GetCoeff(static_cast<double>(pi)*IndexScale)};
46 const double coeff2{GetCoeff(static_cast<double>(CubicPhaseCount - pi)*IndexScale)};
47 const double coeff3{GetCoeff(static_cast<double>(CubicPhaseCount*2 - pi)*IndexScale)};
49 const double scale{1.0 / (coeff0 + coeff1 + coeff2 + coeff3)};
50 mTable[pi].mCoeffs[0] = static_cast<float>(coeff0 * scale);
51 mTable[pi].mCoeffs[1] = static_cast<float>(coeff1 * scale);
52 mTable[pi].mCoeffs[2] = static_cast<float>(coeff2 * scale);
53 mTable[pi].mCoeffs[3] = static_cast<float>(coeff3 * scale);
56 /* Fill in the coefficient deltas. */
57 for(std::size_t pi{0};pi < CubicPhaseCount-1;++pi)
59 mTable[pi].mDeltas[0] = mTable[pi+1].mCoeffs[0] - mTable[pi].mCoeffs[0];
60 mTable[pi].mDeltas[1] = mTable[pi+1].mCoeffs[1] - mTable[pi].mCoeffs[1];
61 mTable[pi].mDeltas[2] = mTable[pi+1].mCoeffs[2] - mTable[pi].mCoeffs[2];
62 mTable[pi].mDeltas[3] = mTable[pi+1].mCoeffs[3] - mTable[pi].mCoeffs[3];
65 const std::size_t pi{CubicPhaseCount - 1};
66 mTable[pi].mDeltas[0] = 0.0f - mTable[pi].mCoeffs[0];
67 mTable[pi].mDeltas[1] = mTable[0].mCoeffs[0] - mTable[pi].mCoeffs[1];
68 mTable[pi].mDeltas[2] = mTable[0].mCoeffs[1] - mTable[pi].mCoeffs[2];
69 mTable[pi].mDeltas[3] = mTable[0].mCoeffs[2] - mTable[pi].mCoeffs[3];
73 const GaussFilterArray GaussFilter{};
75 } // namespace
77 const CubicTable gGaussianFilter{GaussFilter.mTable};
79 CubicFilter::CubicFilter()
81 static constexpr double IndexScale{512.0 / double{sTableSteps*2}};
82 /* Only half the coefficients need to be iterated here, since Coeff2 and
83 * Coeff3 are just Coeff1 and Coeff0 in reverse respectively.
85 for(size_t i{0};i < sTableSteps/2;++i)
87 const double coeff0{GetCoeff(static_cast<double>(sTableSteps + i)*IndexScale)};
88 const double coeff1{GetCoeff(static_cast<double>(i)*IndexScale)};
89 const double coeff2{GetCoeff(static_cast<double>(sTableSteps - i)*IndexScale)};
90 const double coeff3{GetCoeff(static_cast<double>(sTableSteps*2 - i)*IndexScale)};
92 const double scale{1.0 / (coeff0 + coeff1 + coeff2 + coeff3)};
93 mFilter[sTableSteps + i] = static_cast<float>(coeff0 * scale);
94 mFilter[i] = static_cast<float>(coeff1 * scale);
95 mFilter[sTableSteps - i] = static_cast<float>(coeff2 * scale);
96 mFilter[sTableSteps*2 - i] = static_cast<float>(coeff3 * scale);