| @@ -19,6 +19,7 @@ | |||||
| // | // | ||||
| #include <cmath> // std::floor | #include <cmath> // std::floor | ||||
| #include "../math/constants.h" // F_PI | |||||
| #include <functional> // std::function | #include <functional> // std::function | ||||
| #include <limits> // std::numeric_limits | #include <limits> // std::numeric_limits | ||||
| #include <memory> // std::shared_ptr | #include <memory> // std::shared_ptr | ||||
| @@ -337,10 +338,33 @@ public: | |||||
| if (in_rate == out_rate) | if (in_rate == out_rate) | ||||
| return m_in->get(buf, frames); | return m_in->get(buf, frames); | ||||
| // 16 taps lanczos filter | |||||
| const size_t window_size = 16; | |||||
| const float window_center = 8.0f; | |||||
| const size_t constexpr lanczos_size = window_size * 64; | |||||
| const float lanczos_lut_scale = (lanczos_size - 1) / (window_center + 1.0f); | |||||
| static auto build_lanczos = [&]() | |||||
| { | |||||
| std::array<float, lanczos_size> ret; | |||||
| for (int k = 0; k < lanczos_size; ++k) | |||||
| { | |||||
| float dist = float(k) * F_PI / lanczos_lut_scale; | |||||
| float lanczos = 1.0f; | |||||
| if (dist > 0.0f) lanczos = window_center * std::sinf(dist) * std::sinf(dist / window_center) / (dist * dist); | |||||
| ret[k] = lanczos; | |||||
| } | |||||
| return ret; | |||||
| }; | |||||
| static auto const lanczos_lut = build_lanczos(); | |||||
| for (size_t n = 0; n < frames; ++n, m_pos += in_rate) | for (size_t n = 0; n < frames; ++n, m_pos += in_rate) | ||||
| { | { | ||||
| // Fill internal buffer if we don’t have enough data | // Fill internal buffer if we don’t have enough data | ||||
| while (m_cache.size() / channels < m_pos / out_rate + 2) | |||||
| while (m_cache.size() / channels < m_pos / out_rate + window_size) | |||||
| { | { | ||||
| // Remove obsolete frames on the left | // Remove obsolete frames on the left | ||||
| size_t todelete = std::min(m_pos / out_rate, m_cache.size() / channels); | size_t todelete = std::min(m_pos / out_rate, m_cache.size() / channels); | ||||
| @@ -358,8 +382,15 @@ public: | |||||
| for (size_t ch = 0; ch < channels; ++ch) | for (size_t ch = 0; ch < channels; ++ch) | ||||
| { | { | ||||
| *buf++ = m_cache[n0 * channels + ch] * (1.f - alpha) | |||||
| + m_cache[(n0 + 1) * channels + ch] * alpha; | |||||
| // lanczos upsampling | |||||
| T value = T(); | |||||
| for (size_t wi = 0; wi < window_size; ++wi) | |||||
| { | |||||
| float dist = std::abs(wi - window_center - alpha); | |||||
| float lanczos = lanczos_lut[int(dist * lanczos_lut_scale)]; | |||||
| value += m_cache[(n0 + wi) * channels + ch] * lanczos; | |||||
| } | |||||
| *buf++ = value; | |||||
| } | } | ||||
| } | } | ||||