|
@@ -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 |