diff --git a/cmake/SfizzSIMDSourceFiles.cmake b/cmake/SfizzSIMDSourceFiles.cmake index ef0e1d1b..962d0fb0 100644 --- a/cmake/SfizzSIMDSourceFiles.cmake +++ b/cmake/SfizzSIMDSourceFiles.cmake @@ -3,6 +3,7 @@ macro(sfizz_add_simd_sources SOURCES_VAR PREFIX) list (APPEND ${SOURCES_VAR} ${PREFIX}/sfizz/SIMDSSE.cpp + ${PREFIX}/sfizz/SIMDHelpers.cpp ${PREFIX}/sfizz/SIMDNEON.cpp ${PREFIX}/sfizz/SIMDDummy.cpp) diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 04f33cc9..95519ac6 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -60,7 +60,7 @@ void readBaseFile(SndfileHandle& sndFile, sfz::FileAudioBuffer& output, uint32_t output.clear(); sfz::Buffer tempReadBuffer { 2 * numFrames }; sndFile.readf(tempReadBuffer.data(), numFrames); - sfz::readInterleaved(tempReadBuffer, output.getSpan(0), output.getSpan(1)); + sfz::readInterleaved(tempReadBuffer, output.getSpan(0), output.getSpan(1)); } if (reverse) { @@ -87,7 +87,6 @@ std::unique_ptr readFromFile(SndfileHandle& sndFile, uint3 return outputBuffer; } -template void streamFromFile(SndfileHandle& sndFile, uint32_t numFrames, sfz::Oversampling factor, bool reverse, sfz::FileAudioBuffer& output, std::atomic* filledFrames = nullptr) { if (factor == sfz::Oversampling::x1) { @@ -400,7 +399,7 @@ void sfz::FilePool::loadingThread() noexcept continue; } const auto frames = static_cast(sndFile.frames()); - streamFromFile(sndFile, frames, oversamplingFactor, promise->fileId.isReverse(), promise->fileData, &promise->availableFrames); + streamFromFile(sndFile, frames, oversamplingFactor, promise->fileId.isReverse(), promise->fileData, &promise->availableFrames); promise->dataStatus = FilePromise::DataStatus::Ready; const auto loadDuration = std::chrono::high_resolution_clock::now() - loadStartTime; logger.logFileTime(waitDuration, loadDuration, frames, promise->fileId.filename()); diff --git a/src/sfizz/SIMDHelpers.cpp b/src/sfizz/SIMDHelpers.cpp index b3081621..5308f601 100644 --- a/src/sfizz/SIMDHelpers.cpp +++ b/src/sfizz/SIMDHelpers.cpp @@ -1,12 +1,20 @@ #include "SIMDHelpers.h" #include +#include "cpuid/cpuinfo.hpp" -namespace sfz{ +#include "SIMDConfig.h" -static std::array(sfz::SIMDOps::_sentinel)> simdStatus; +#if SFIZZ_HAVE_SSE2 +#include +#include +#endif + +namespace sfz { + +static std::array(SIMDOps::_sentinel)> simdStatus; static bool simdStatusInitialized = false; -static void resetSIMDStatus() +void resetSIMDStatus() { simdStatus[static_cast(SIMDOps::writeInterleaved)] = true; simdStatus[static_cast(SIMDOps::readInterleaved)] = true; @@ -32,14 +40,15 @@ static void resetSIMDStatus() simdStatusInitialized = true; } -static void setSIMDOpStatus(SIMDOps op, bool status) +void setSIMDOpStatus(SIMDOps op, bool status) { if (!simdStatusInitialized) resetSIMDStatus(); simdStatus[static_cast(op)] = status; } -static bool getSIMDOpStatus(SIMDOps op) + +bool getSIMDOpStatus(SIMDOps op) { if (!simdStatusInitialized) resetSIMDStatus(); @@ -47,5 +56,85 @@ static bool getSIMDOpStatus(SIMDOps op) return simdStatus[static_cast(op)]; } +constexpr uintptr_t TypeAlignment = 4; + +template +inline void tickRead(const T*& input, T*& outputLeft, T*& outputRight) +{ + *outputLeft++ = *input++; + *outputRight++ = *input++; +} + +template +inline void tickWrite(T*& output, const T*& inputLeft, const T*& inputRight) +{ + *output++ = *inputLeft++; + *output++ = *inputRight++; +} + +void readInterleaved(const float* input, float* outputLeft, float* outputRight, unsigned inputSize) noexcept +{ + const auto sentinel = input + inputSize - 1; + cpuid::cpuinfo cpuInfo; + if (getSIMDOpStatus(SIMDOps::readInterleaved)) { +#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386 + if (cpuInfo.has_sse()) { + const auto* lastAligned = prevAligned(input + inputSize - 4); + while (unaligned(input, outputLeft, outputRight) && input < lastAligned) + tickRead(input, outputLeft, outputRight); + + while (input < lastAligned) { + auto register0 = _mm_load_ps(input); + auto register1 = _mm_load_ps(input + 4); + auto register2 = register0; + // register 2 holds the copy of register 0 that is going to get erased by the first operation + // Remember that the bit mask reads from the end; 10 00 10 00 means + // "take 0 from a, take 2 from a, take 0 from b, take 2 from b" + register0 = _mm_shuffle_ps(register0, register1, 0b10001000); + register1 = _mm_shuffle_ps(register2, register1, 0b11011101); + _mm_store_ps(outputLeft, register0); + _mm_store_ps(outputRight, register1); + incrementAll<4>(input, input, outputLeft, outputRight); + } + // Fallthrough from lastAligned to sentinel + } +#endif + } + + while (input < sentinel) + tickRead(input, outputLeft, outputRight); +} + +void writeInterleaved(const float* inputLeft, const float* inputRight, float* output, unsigned outputSize) noexcept +{ + const auto sentinel = output + outputSize - 1; + + cpuid::cpuinfo cpuInfo; + if (getSIMDOpStatus(SIMDOps::readInterleaved)) { +#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386 + if (cpuInfo.has_sse()) { + const auto* lastAligned = prevAligned(output + outputSize - 4); + + while (unaligned(output, inputRight, inputLeft) && output < lastAligned) + tickWrite(output, inputLeft, inputRight); + + while (output < lastAligned) { + const auto lInRegister = _mm_load_ps(inputLeft); + const auto rInRegister = _mm_load_ps(inputRight); + const auto outRegister1 = _mm_unpacklo_ps(lInRegister, rInRegister); + _mm_store_ps(output, outRegister1); + const auto outRegister2 = _mm_unpackhi_ps(lInRegister, rInRegister); + _mm_store_ps(output + 4, outRegister2); + incrementAll<4>(output, output, inputLeft, inputRight); + } + // fallthrough from lastAligned to sentinel + } +#endif + } + + while (output < sentinel) + tickWrite(output, inputLeft, inputRight); +} + } diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 732d615c..5bce8a78 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -69,18 +69,35 @@ enum class SIMDOps { upsampling, _sentinel // }; + // Enable or disable SIMD accelerators at runtime -static void setSIMDOpStatus(SIMDOps op, bool status); -static bool getSIMDOpStatus(SIMDOps op); +void setSIMDOpStatus(SIMDOps op, bool status); +bool getSIMDOpStatus(SIMDOps op); +constexpr uintptr_t ByteAlignmentMask { config::defaultAlignment - 1 }; -namespace _internals { - template - inline void snippetRead(const T*& input, T*& outputLeft, T*& outputRight) - { - *outputLeft++ = *input++; - *outputRight++ = *input++; - } +template +T* nextAligned(const T* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) + ByteAlignmentMask & (~ByteAlignmentMask)); +} + +template +T* prevAligned(const T* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) & (~ByteAlignmentMask)); +} + +template +bool unaligned(const T* ptr) +{ + return (reinterpret_cast(ptr) & ByteAlignmentMask )!= 0; +} + +template +bool unaligned(const T* ptr1, Args... rest) +{ + return unaligned(ptr1) || unaligned(rest...); } /** @@ -89,33 +106,21 @@ namespace _internals { * The output size will be the minimum of the input span and output spans size. * * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version * @param input * @param outputLeft * @param outputRight */ -template -void readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept +void readInterleaved(const float* input, float* outputLeft, float* outputRight, unsigned inputSize) noexcept; + +inline void readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept { // The size of the output is not big enough for the input... CHECK(outputLeft.size() >= input.size() / 2); CHECK(outputRight.size() >= input.size() / 2); - - auto* in = input.begin(); - auto* lOut = outputLeft.begin(); - auto* rOut = outputRight.begin(); - while (in < (input.end() - 1) && lOut < outputLeft.end() && rOut < outputRight.end()) - _internals::snippetRead(in, lOut, rOut); + const auto size = min(input.size(), 2 * outputLeft.size(), 2 * outputRight.size()); + readInterleaved(input.data(), outputLeft.data(), outputRight.data(), size); } -namespace _internals { - template - inline void snippetWrite(T*& output, const T*& inputLeft, const T*& inputRight) - { - *output++ = *inputLeft++; - *output++ = *inputRight++; - } -} /** * @brief Write a pair of left and right stereo input into a single buffer interleaved. @@ -123,30 +128,21 @@ namespace _internals { * The output size will be the minimum of the input spans and output span size. * * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version * @param inputLeft * @param inputRight * @param output */ -template -void writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept +void writeInterleaved(const float* inputLeft, const float* inputRight, float* output, unsigned outputSize) noexcept; + +inline void writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept { - CHECK(inputLeft.size() <= output.size() / 2); - CHECK(inputRight.size() <= output.size() / 2); - - auto* lIn = inputLeft.begin(); - auto* rIn = inputRight.begin(); - auto* out = output.begin(); - while (lIn < inputLeft.end() && rIn < inputRight.end() && out < (output.end() - 1)) - _internals::snippetWrite(out, lIn, rIn); + // Not enough data in the inputs + CHECK(inputLeft.size() >= output.size() / 2); + CHECK(inputRight.size() >= output.size() / 2); + const auto size = min(output.size(), 2 * inputLeft.size(), 2 * inputRight.size()); + writeInterleaved(inputLeft.data(), inputRight.data(), output.data(), size); } -// Specializations -template <> -void writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept; -template <> -void readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept; - /** * @brief Fill a buffer with a value; comparable to std::fill in essence. * diff --git a/src/sfizz/SIMDSSE.cpp b/src/sfizz/SIMDSSE.cpp index ae0cd07e..b0dcf2d9 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -12,116 +12,9 @@ #include #include #include - #include "mathfuns/sse_mathfun.h" -using Type = float; -constexpr uintptr_t TypeAlignment { 4 }; -constexpr uintptr_t ByteAlignment { TypeAlignment * sizeof(Type) }; -constexpr uintptr_t ByteAlignmentMask { ByteAlignment - 1 }; - -struct AlignmentSentinels { - float* nextAligned; - float* lastAligned; -}; - -float* nextAligned(const float* ptr) -{ - return reinterpret_cast((reinterpret_cast(ptr) + ByteAlignmentMask) & (~ByteAlignmentMask)); -} - -float* prevAligned(const float* ptr) -{ - return reinterpret_cast(reinterpret_cast(ptr) & (~ByteAlignmentMask)); -} - -bool unaligned(const float* ptr) -{ - return (reinterpret_cast(ptr) & ByteAlignmentMask) != 0; -} - -template -bool unaligned(const float* ptr1, Args... rest) -{ - return unaligned(ptr1) || unaligned(rest...); -} - -template <> -void sfz::readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept -{ - // The size of the outputs is not big enough for the input... - CHECK(outputLeft.size() >= input.size() / 2); - CHECK(outputRight.size() >= input.size() / 2); - // Input is too small - CHECK(input.size() > 1); - - auto* in = input.begin(); - auto* lOut = outputLeft.begin(); - auto* rOut = outputRight.begin(); - - const auto size = std::min(input.size(), std::min(outputLeft.size() * 2, outputRight.size() * 2)); - const auto* lastAligned = prevAligned(input.begin() + size - TypeAlignment); - - while (unaligned(in, lOut, rOut) && in < lastAligned) - _internals::snippetRead(in, lOut, rOut); - - while (in < lastAligned) { - auto register0 = _mm_load_ps(in); - in += TypeAlignment; - auto register1 = _mm_load_ps(in); - in += TypeAlignment; - auto register2 = register0; - // register 2 holds the copy of register 0 that is going to get erased by the first operation - // Remember that the bit mask reads from the end; 10 00 10 00 means - // "take 0 from a, take 2 from a, take 0 from b, take 2 from b" - register0 = _mm_shuffle_ps(register0, register1, 0b10001000); - register1 = _mm_shuffle_ps(register2, register1, 0b11011101); - _mm_store_ps(lOut, register0); - _mm_store_ps(rOut, register1); - lOut += TypeAlignment; - rOut += TypeAlignment; - } - - while (in < input.end() - 1) - _internals::snippetRead(in, lOut, rOut); -} - -template <> -void sfz::writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept -{ - // The size of the output is not big enough for the inputs... - CHECK(inputLeft.size() <= output.size() / 2); - CHECK(inputRight.size() <= output.size() / 2); - - auto* lIn = inputLeft.begin(); - auto* rIn = inputRight.begin(); - auto* out = output.begin(); - - const auto size = std::min(output.size(), std::min(inputLeft.size(), inputRight.size()) * 2); - const auto* lastAligned = prevAligned(output.begin() + size - TypeAlignment); - - while (unaligned(out, rIn, lIn) && out < lastAligned) - _internals::snippetWrite(out, lIn, rIn); - - while (out < lastAligned) { - const auto lInRegister = _mm_load_ps(lIn); - const auto rInRegister = _mm_load_ps(rIn); - - const auto outRegister1 = _mm_unpacklo_ps(lInRegister, rInRegister); - _mm_store_ps(out, outRegister1); - out += TypeAlignment; - - const auto outRegister2 = _mm_unpackhi_ps(lInRegister, rInRegister); - _mm_store_ps(out, outRegister2); - out += TypeAlignment; - - lIn += TypeAlignment; - rIn += TypeAlignment; - } - - while (out < output.end() - 1) - _internals::snippetWrite(out, lIn, rIn); -} +constexpr uintptr_t TypeAlignment = 4; template <> void sfz::fill(absl::Span output, float value) noexcept diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index 44c837c4..06133ef0 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -122,7 +122,8 @@ TEST_CASE("[Helpers] Interleaved read") std::array expected { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, false); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -139,7 +140,8 @@ TEST_CASE("[Helpers] Interleaved read unaligned end") std::array expected { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, false); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -156,7 +158,8 @@ TEST_CASE("[Helpers] Small interleaved read unaligned end") std::array expected { 0.0f, 1.0f, 2.0f, 10.0f, 11.0f, 12.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, false); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -173,7 +176,8 @@ TEST_CASE("[Helpers] Interleaved read -- SIMD") std::array expected = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, true); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -190,7 +194,8 @@ TEST_CASE("[Helpers] Interleaved read unaligned end -- SIMD") std::array expected = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, true); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -207,7 +212,8 @@ TEST_CASE("[Helpers] Small interleaved read unaligned end -- SIMD") std::array expected { 0.0f, 1.0f, 2.0f, 10.0f, 11.0f, 12.0f }; std::array leftOutput; std::array rightOutput; - sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, true); + sfz::readInterleaved(input, absl::MakeSpan(leftOutput), absl::MakeSpan(rightOutput)); std::array real; auto realIdx = 0; @@ -226,8 +232,10 @@ TEST_CASE("[Helpers] Interleaved read SIMD vs Scalar") std::array leftOutputSIMD; std::array rightOutputSIMD; std::iota(input.begin(), input.end(), 0.0f); - sfz::readInterleaved(input, absl::MakeSpan(leftOutputScalar), absl::MakeSpan(rightOutputScalar)); - sfz::readInterleaved(input, absl::MakeSpan(leftOutputSIMD), absl::MakeSpan(rightOutputSIMD)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, false); + sfz::readInterleaved(input, absl::MakeSpan(leftOutputScalar), absl::MakeSpan(rightOutputScalar)); + sfz::setSIMDOpStatus(sfz::SIMDOps::readInterleaved, true); + sfz::readInterleaved(input, absl::MakeSpan(leftOutputSIMD), absl::MakeSpan(rightOutputSIMD)); REQUIRE(leftOutputScalar == leftOutputSIMD); REQUIRE(rightOutputScalar == rightOutputSIMD); } @@ -247,7 +255,8 @@ TEST_CASE("[Helpers] Interleaved write") std::array rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f }; std::array output; std::array expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, false); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -257,7 +266,8 @@ TEST_CASE("[Helpers] Interleaved write unaligned end") std::array rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f }; std::array output; std::array expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f, 8.0f, 18.0f, 9.0f, 19.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, false); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -267,7 +277,8 @@ TEST_CASE("[Helpers] Small interleaved write unaligned end") std::array rightInput { 10.0f, 11.0f, 12.0f }; std::array output; std::array expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, false); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -286,7 +297,8 @@ TEST_CASE("[Helpers] Interleaved write -- SIMD") std::array rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f }; std::array output; std::array expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, true); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -296,7 +308,7 @@ TEST_CASE("[Helpers] Interleaved write unaligned end -- SIMD") std::array rightInput { 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f }; std::array output; std::array expected = { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f, 3.0f, 13.0f, 4.0f, 14.0f, 5.0f, 15.0f, 6.0f, 16.0f, 7.0f, 17.0f, 8.0f, 18.0f, 9.0f, 19.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -306,7 +318,8 @@ TEST_CASE("[Helpers] Small interleaved write unaligned end -- SIMD") std::array rightInput { 10.0f, 11.0f, 12.0f }; std::array output; std::array expected { 0.0f, 10.0f, 1.0f, 11.0f, 2.0f, 12.0f }; - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, true); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -318,8 +331,10 @@ TEST_CASE("[Helpers] Interleaved write SIMD vs Scalar") std::array outputSIMD; std::iota(leftInput.begin(), leftInput.end(), 0.0f); std::iota(rightInput.begin(), rightInput.end(), static_cast(medBufferSize)); - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(outputScalar)); - sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(outputSIMD)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, false); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(outputScalar)); + sfz::setSIMDOpStatus(sfz::SIMDOps::writeInterleaved, true); + sfz::writeInterleaved(leftInput, rightInput, absl::MakeSpan(outputSIMD)); REQUIRE(outputScalar == outputSIMD); }