diff --git a/sfizz/SIMDDummy.cpp b/sfizz/SIMDDummy.cpp index 507c15d5..fd19d1c2 100644 --- a/sfizz/SIMDDummy.cpp +++ b/sfizz/SIMDDummy.cpp @@ -126,6 +126,13 @@ void subtract(absl::Span input, absl::Span outp subtract(input, output); } +template <> +void subtract(const float value, absl::Span output) noexcept +{ + subtract(value, output); +} + + template <> void copy(absl::Span input, absl::Span output) noexcept { diff --git a/sfizz/SIMDHelpers.h b/sfizz/SIMDHelpers.h index db4de29e..6a9b2a90 100644 --- a/sfizz/SIMDHelpers.h +++ b/sfizz/SIMDHelpers.h @@ -374,6 +374,21 @@ inline void snippetSubtract(const T*& input, T*& output) *output++ -= *input++; } +template +inline void snippetSubtract(const T value, T*& output) +{ + *output++ -= value; +} + +template +void subtract(const T value, absl::Span output) noexcept +{ + auto* out = output.begin(); + auto* sentinel = output.end(); + while (out < sentinel) + snippetSubtract(value, out); +} + template void subtract(absl::Span input, absl::Span output) noexcept { @@ -388,6 +403,8 @@ void subtract(absl::Span input, absl::Span output) noexcept template <> void subtract(absl::Span input, absl::Span output) noexcept; +template <> +void subtract(const float value, absl::Span output) noexcept; template void snippetCopy(const T*& input, T*& output) diff --git a/sfizz/SIMDSSE.cpp b/sfizz/SIMDSSE.cpp index 63a11fa4..69b9fd07 100644 --- a/sfizz/SIMDSSE.cpp +++ b/sfizz/SIMDSSE.cpp @@ -564,6 +564,26 @@ void subtract(absl::Span input, absl::Span outp snippetSubtract(in, out); } +template <> +void subtract(const float value, absl::Span output) noexcept +{ + auto* out = output.begin(); + auto* sentinel = output.end(); + const auto* lastAligned = prevAligned(sentinel); + + while (unaligned(out) && out < lastAligned) + snippetSubtract(value, out); + + auto mmValue = _mm_set_ps1(value); + while (out < lastAligned) { + _mm_store_ps(out, _mm_sub_ps(_mm_load_ps(out), mmValue)); + out += TypeAlignment; + } + + while (out < sentinel) + snippetSubtract(value, out); +} + template <> void copy(absl::Span input, absl::Span output) noexcept {