| @@ -2,6 +2,7 @@ | |||||
| // Lol Engine | // Lol Engine | ||||
| // | // | ||||
| // Copyright © 2010–2024 Sam Hocevar <sam@hocevar.net> | // Copyright © 2010–2024 Sam Hocevar <sam@hocevar.net> | ||||
| // 2024 NuSan | |||||
| // | // | ||||
| // Lol Engine is free software. It comes without any warranty, to | // Lol Engine is free software. It comes without any warranty, to | ||||
| // the extent permitted by applicable law. You can redistribute it | // the extent permitted by applicable law. You can redistribute it | ||||
| @@ -23,41 +24,40 @@ | |||||
| namespace lol::interp | namespace lol::interp | ||||
| { | { | ||||
| // Lanczos interpolation | |||||
| // SIZE: number of lobes of the sinc function that contribute to the interpolation | |||||
| // PRECISION: number of samples per lobe in the kernel | |||||
| template<typename T, size_t SIZE = 16, size_t PRECISION = 64> | template<typename T, size_t SIZE = 16, size_t PRECISION = 64> | ||||
| class lanczos | class lanczos | ||||
| { | { | ||||
| public: | public: | ||||
| lanczos() | lanczos() | ||||
| { | { | ||||
| T const window_center = SIZE / 2; | |||||
| T const lut_scale = (SIZE * PRECISION - 1) / (window_center + 1); | |||||
| for (size_t k = 0; k < SIZE * PRECISION; ++k) | for (size_t k = 0; k < SIZE * PRECISION; ++k) | ||||
| { | { | ||||
| T dist = T(k) * F_PI / lut_scale; | |||||
| m_lut[k] = dist ? window_center * std::sin(dist) * std::sin(dist / window_center) / (dist * dist) : T(1); | |||||
| T dist = T(k) * F_PI / m_scale; | |||||
| m_kernel[k] = dist ? m_center * std::sin(dist) * std::sin(dist / m_center) / (dist * dist) : T(1); | |||||
| } | } | ||||
| } | } | ||||
| T get(T *data, size_t stride, T alpha) | |||||
| T get(T *data, size_t stride, T offset) const | |||||
| { | { | ||||
| T const window_center = SIZE / 2; | |||||
| T const lut_scale = (SIZE * PRECISION - 1) / (window_center + 1); | |||||
| T ret(0); | T ret(0); | ||||
| for (size_t k = 0; k < SIZE; ++k) | for (size_t k = 0; k < SIZE; ++k) | ||||
| { | { | ||||
| float dist = std::abs(k - window_center - alpha); | |||||
| float lanczos = m_lut[size_t(dist * lut_scale)]; | |||||
| ret += data[k * stride] * lanczos; | |||||
| float dist = std::abs(k - m_center - offset); | |||||
| ret += data[k * stride] * m_kernel[size_t(dist * m_scale)]; | |||||
| } | } | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| size_t const size() { return SIZE; } | |||||
| size_t const size() const { return SIZE; } | |||||
| private: | private: | ||||
| static size_t const center = T(SIZE) / 2; | |||||
| static inline T const m_center = SIZE / 2; | |||||
| static inline T const m_scale = (SIZE * PRECISION - 1) / (m_center + 1); | |||||
| std::array<T, SIZE * PRECISION> m_lut; | |||||
| std::array<T, SIZE * PRECISION> m_kernel; | |||||
| }; | }; | ||||
| } // namespace lol::interp | } // namespace lol::interp | ||||