diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 7d6f8e03..f8b898ae 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -723,12 +723,39 @@ template <> void copy(absl::Span input, absl::Span output) noexcept; namespace _internals { + // Number of elements in the table, odd for equal volume at center + constexpr int panSize = 4095; + + // Table of pan values for the left channel, extra element for safety + const auto panData = []() + { + std::array pan; + int i = 0; + + for (; i < panSize; ++i) + pan[i] = std::cos(i * (piTwo / (panSize - 1))); + + for (; i < static_cast(pan.size()); ++i) + pan[i] = pan[panSize - 1]; + + return pan; + }(); + template inline void snippetPan(const T*& pan, T*& left, T*& right) { - const auto circlePan = piFour * (static_cast(1.0) + *pan++); - *left++ *= std::cos(circlePan); - *right++ *= std::sin(circlePan); + T p = ((*pan++) + T{1.0}) * T{0.5}; + p = std::max(0, std::min(p, 1)); + + auto lookUp = [](T pan) -> T + { + // reduce range, round to nearest + int index = static_cast(T{0.5} + pan * (panSize - 1)); + return panData[index]; + }; + + *left++ = lookUp(p); + *right++ = lookUp(1 - p); } }