diff --git a/benchmarks/BM_looping.cpp b/benchmarks/BM_looping.cpp deleted file mode 100644 index 6a465ffc..00000000 --- a/benchmarks/BM_looping.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause - -// This code is part of the sfizz library and is licensed under a BSD 2-clause -// license. You should have receive a LICENSE.md file along with the code. -// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz - -#include -#include "SIMDHelpers.h" -#include -#include -#include -#include - -// In this one we have an array of indices - -constexpr int loopStart { 5 }; -constexpr int loopEnd { 1076 }; -constexpr float maxJump { 4 }; - -class LoopingFixture : public benchmark::Fixture { -public: - void SetUp(const ::benchmark::State& state) { - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, maxJump }; - indices = std::vector(state.range(0)); - leftCoeffs = std::vector(state.range(0)); - rightCoeffs = std::vector(state.range(0)); - jumps = std::vector(state.range(0)); - absl::c_generate(jumps, [&]() { return dist(gen); }); - } - - void TearDown(const ::benchmark::State& /* state */) { - - } - - std::vector indices; - std::vector leftCoeffs; - std::vector rightCoeffs; - std::vector jumps; -}; - - -BENCHMARK_DEFINE_F(LoopingFixture, Scalar)(benchmark::State& state) { - for (auto _ : state) - { - sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 2.5f, loopEnd, loopStart); - } -} - -BENCHMARK_DEFINE_F(LoopingFixture, SIMD)(benchmark::State& state) { - for (auto _ : state) - { - sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 2.5f, loopEnd, loopStart); - } -} - -BENCHMARK_DEFINE_F(LoopingFixture, Scalar_Unaligned)(benchmark::State& state) { - for (auto _ : state) - { - sfz::loopingSFZIndex(absl::MakeSpan(jumps).subspan(1), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1), absl::MakeSpan(indices).subspan(3), 2.5f, loopEnd, loopStart); - } -} - -BENCHMARK_DEFINE_F(LoopingFixture, SIMD_Unaligned)(benchmark::State& state) { - for (auto _ : state) - { - sfz::loopingSFZIndex(absl::MakeSpan(jumps).subspan(1), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1), absl::MakeSpan(indices).subspan(3), 2.5f, loopEnd, loopStart); - } -} - - -// Register the function as a benchmark -BENCHMARK_REGISTER_F(LoopingFixture, Scalar)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(LoopingFixture, SIMD)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(LoopingFixture, Scalar_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(LoopingFixture, SIMD_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_MAIN(); diff --git a/benchmarks/BM_saturating.cpp b/benchmarks/BM_saturating.cpp deleted file mode 100644 index d6bb2427..00000000 --- a/benchmarks/BM_saturating.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause - -// This code is part of the sfizz library and is licensed under a BSD 2-clause -// license. You should have receive a LICENSE.md file along with the code. -// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz - -#include "SIMDHelpers.h" -#include -#include -#include -#include -#include - -// In this one we have an array of indices - -constexpr int loopEnd { 1076 }; -constexpr float maxJump { 4 }; - -class SaturatingFixture : public benchmark::Fixture { -public: - void SetUp(const ::benchmark::State& state) { - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, maxJump }; - indices = std::vector(state.range(0)); - leftCoeffs = std::vector(state.range(0)); - rightCoeffs = std::vector(state.range(0)); - jumps = std::vector(state.range(0)); - absl::c_generate(jumps, [&]() { return dist(gen); }); - } - - void TearDown(const ::benchmark::State& /* state */) { - - } - - std::vector indices; - std::vector leftCoeffs; - std::vector rightCoeffs; - std::vector jumps; -}; - - -BENCHMARK_DEFINE_F(SaturatingFixture, Scalar)(benchmark::State& state) { - for (auto _ : state) - { - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 2.5f, loopEnd); - } -} - -BENCHMARK_DEFINE_F(SaturatingFixture, SIMD)(benchmark::State& state) { - for (auto _ : state) - { - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 2.5f, loopEnd); - } -} - -BENCHMARK_DEFINE_F(SaturatingFixture, Scalar_Unaligned)(benchmark::State& state) { - for (auto _ : state) - { - sfz::saturatingSFZIndex(absl::MakeSpan(jumps).subspan(1), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1), absl::MakeSpan(indices).subspan(3), 2.5f, loopEnd); - } -} - -BENCHMARK_DEFINE_F(SaturatingFixture, SIMD_Unaligned)(benchmark::State& state) { - for (auto _ : state) - { - sfz::saturatingSFZIndex(absl::MakeSpan(jumps).subspan(1), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1), absl::MakeSpan(indices).subspan(3), 2.5f, loopEnd); - } -} - - -// Register the function as a benchmark -BENCHMARK_REGISTER_F(SaturatingFixture, Scalar)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(SaturatingFixture, SIMD)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(SaturatingFixture, Scalar_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_REGISTER_F(SaturatingFixture, SIMD_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12)); -BENCHMARK_MAIN(); diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index b2fa4195..0fa42459 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -41,8 +41,6 @@ sfizz_add_benchmark(bm_read BM_readInterleaved.cpp) sfizz_add_benchmark(bm_mathfuns BM_mathfuns.cpp) sfizz_add_benchmark(bm_gain BM_gain.cpp) sfizz_add_benchmark(bm_divide BM_divide.cpp) -sfizz_add_benchmark(bm_looping BM_looping.cpp) -sfizz_add_benchmark(bm_saturating BM_saturating.cpp) sfizz_add_benchmark(bm_ramp BM_ramp.cpp) sfizz_add_benchmark(bm_ADSR BM_ADSR.cpp) target_link_libraries(bm_ADSR PRIVATE sfizz::sfizz) diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 840853a3..4be2cee5 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -152,120 +152,6 @@ void fill(absl::Span output, T value) noexcept absl::c_fill(output, value); } -namespace _internals { - template - inline void snippetSaturatingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, int*& index, T& floatIndex, T loopEnd) - { - floatIndex += *jump; - if (floatIndex >= loopEnd) { - floatIndex = loopEnd; - *index = static_cast(floatIndex) - 1; - *rightCoeff = static_cast(1.0); - *leftCoeff = static_cast(0.0); - } else { - *index = static_cast(floatIndex); - *rightCoeff = floatIndex - *index; - *leftCoeff = static_cast(1.0) - *rightCoeff; - } - incrementAll(index, leftCoeff, rightCoeff, jump); - } -} - -/** - * @brief Computes an integer index and 2 float coefficients corresponding to the - * linear interpolation procedure. This version will saturate the index to the upper - * bound if the upper bound is reached. - * - * The indices are computed starting from the given floatIndex, and each increment - * is given by the elements of jumps. - * The output size will be the minimum of the inputs span and outputs span size. - * - * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version - * @param jumps the floating point increments to the index - * @param leftCoeffs the linear interpolation coefficients for the left value - * @param rightCoeffs the linear interpolation coefficients for the right value - * @param indices the integer sample indices for the left values; the right values - * for interpolation at index i are (indices[i] + 1) and not indices[i+1] - * @param floatIndex the starting floating point index - * @param loopEnd the end of the "loop" which is not really a loop because it saturate. - * @return float - */ -template -float saturatingSFZIndex(absl::Span jumps, absl::Span leftCoeffs, absl::Span rightCoeffs, absl::Span indices, T floatIndex, T loopEnd) noexcept -{ - CHECK(indices.size() >= jumps.size()); - CHECK(indices.size() == leftCoeffs.size()); - CHECK(indices.size() == rightCoeffs.size()); - - auto* index = indices.begin(); - auto* leftCoeff = leftCoeffs.begin(); - auto* rightCoeff = rightCoeffs.begin(); - auto* jump = jumps.begin(); - const auto size = min(jumps.size(), indices.size(), leftCoeffs.size(), rightCoeffs.size()); - auto* sentinel = jumps.begin() + size; - - while (jump < sentinel) - _internals::snippetSaturatingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd); - return floatIndex; -} - -template <> -float saturatingSFZIndex(absl::Span jumps, absl::Span leftCoeffs, absl::Span rightCoeffs, absl::Span indices, float floatIndex, float loopEnd) noexcept; - -namespace _internals { - template - inline void snippetLoopingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, int*& index, T& floatIndex, T loopEnd, T loopStart) - { - floatIndex += *jump; - if (floatIndex >= loopEnd) - floatIndex -= loopEnd - loopStart; - *index = static_cast(floatIndex); - *rightCoeff = floatIndex - *index; - *leftCoeff = 1.0f - *rightCoeff; - incrementAll(index, leftCoeff, rightCoeff, jump); - } -} - -/** - * @brief Computes an integer index and 2 float coefficients corresponding to the - * linear interpolation procedure. This version will loop the index at the upper - * bound loopend and restart it at the start of the loop. - * - * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version - * @param jumps the floating point increments to the index - * @param leftCoeffs the linear interpolation coefficients for the left value - * @param rightCoeffs the linear interpolation coefficients for the right value - * @param indices the integer sample indices for the left values; the right values - * for interpolation at index i are (indices[i] + 1) and not indices[i+1] - * @param floatIndex the starting floating point index - * @param loopEnd the end index of the loop - * @param loopStart the start index of the loop - * @return float - */ -template -float loopingSFZIndex(absl::Span jumps, absl::Span leftCoeffs, absl::Span rightCoeffs, absl::Span indices, T floatIndex, T loopEnd, T loopStart) noexcept -{ - CHECK(indices.size() >= jumps.size()); - CHECK(indices.size() == leftCoeffs.size()); - CHECK(indices.size() == rightCoeffs.size()); - - auto* index = indices.begin(); - auto* leftCoeff = leftCoeffs.begin(); - auto* rightCoeff = rightCoeffs.begin(); - auto* jump = jumps.begin(); - const auto size = min(jumps.size(), indices.size(), leftCoeffs.size(), rightCoeffs.size()); - auto* sentinel = jumps.begin() + size; - - while (jump < sentinel) - _internals::snippetLoopingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); - return floatIndex; -} - -template <> -float loopingSFZIndex(absl::Span jumps, absl::Span leftCoeff, absl::Span rightCoeff, absl::Span indices, float floatIndex, float loopEnd, float loopStart) noexcept; - namespace _internals { template inline void snippetGain(T gain, const T*& input, T*& output) diff --git a/src/sfizz/SIMDSSE.cpp b/src/sfizz/SIMDSSE.cpp index 607ae2e7..0c2f1a8a 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -127,120 +127,6 @@ void sfz::multiplyAdd(const float gain, absl::Span inp _internals::snippetMultiplyAdd(gain, in, out); } -template <> -float sfz::loopingSFZIndex(absl::Span jumps, - absl::Span leftCoeffs, - absl::Span rightCoeffs, - absl::Span indices, - float floatIndex, - float loopEnd, - float loopStart) noexcept -{ - CHECK(indices.size() >= jumps.size()); - CHECK(indices.size() == leftCoeffs.size()); - CHECK(indices.size() == rightCoeffs.size()); - - auto index = indices.data(); - auto leftCoeff = leftCoeffs.data(); - auto rightCoeff = rightCoeffs.data(); - auto jump = jumps.data(); - const auto size = min(jumps.size(), indices.size(), leftCoeffs.size(), rightCoeffs.size()); - const auto* sentinel = jumps.begin() + size; - const auto* alignedEnd = prevAligned(sentinel); - - while (unaligned(reinterpret_cast(index), leftCoeff, rightCoeff, jump) && jump < alignedEnd) - _internals::snippetLoopingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); - - auto mmFloatIndex = _mm_set_ps1(floatIndex); - const auto mmJumpBack = _mm_set1_ps(loopEnd - loopStart); - const auto mmLoopEnd = _mm_set1_ps(loopEnd); - while (jump < alignedEnd) { - auto mmOffset = _mm_load_ps(jump); - mmOffset = _mm_add_ps(mmOffset, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOffset), 4))); - mmOffset = _mm_add_ps(mmOffset, _mm_shuffle_ps(_mm_setzero_ps(), mmOffset, 0x40)); - - mmFloatIndex = _mm_add_ps(mmFloatIndex, mmOffset); - const auto mmCompared = _mm_cmpge_ps(mmFloatIndex, mmLoopEnd); - auto mmLoopBack = _mm_sub_ps(mmFloatIndex, mmJumpBack); - mmLoopBack = _mm_and_ps(mmCompared, mmLoopBack); - mmFloatIndex = _mm_andnot_ps(mmCompared, mmFloatIndex); - mmFloatIndex = _mm_add_ps(mmFloatIndex, mmLoopBack); - - auto mmIndices = _mm_cvtps_epi32(_mm_sub_ps(mmFloatIndex, _mm_set_ps1(0.4999999552965164184570312f))); - _mm_store_si128(reinterpret_cast<__m128i*>(index), mmIndices); - - auto mmRight = _mm_sub_ps(mmFloatIndex, _mm_cvtepi32_ps(mmIndices)); - auto mmLeft = _mm_sub_ps(_mm_set_ps1(1.0f), mmRight); - _mm_store_ps(leftCoeff, mmLeft); - _mm_store_ps(rightCoeff, mmRight); - - mmFloatIndex = _mm_shuffle_ps(mmFloatIndex, mmFloatIndex, _MM_SHUFFLE(3, 3, 3, 3)); - // floatingIndex = _mm_cvtss_f32(_mm_shuffle_ps(mmFloatIndex, mmFloatIndex, _MM_SHUFFLE(0, 0, 0, 3)));; - // floatingIndex = *(index + 3) + *(rightCoeff + 3); - incrementAll(index, jump, leftCoeff, rightCoeff); - } - - floatIndex = _mm_cvtss_f32(mmFloatIndex); - while (jump < sentinel) - _internals::snippetLoopingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); - return floatIndex; -} - -template <> -float sfz::saturatingSFZIndex(absl::Span jumps, - absl::Span leftCoeffs, - absl::Span rightCoeffs, - absl::Span indices, - float floatIndex, - float loopEnd) noexcept -{ - CHECK(indices.size() >= jumps.size()); - CHECK(indices.size() == leftCoeffs.size()); - CHECK(indices.size() == rightCoeffs.size()); - - auto index = indices.data(); - auto leftCoeff = leftCoeffs.data(); - auto rightCoeff = rightCoeffs.data(); - auto jump = jumps.data(); - const auto size = min(jumps.size(), indices.size(), leftCoeffs.size(), rightCoeffs.size()); - const auto* sentinel = jumps.begin() + size; - const auto* alignedEnd = prevAligned(sentinel); - - while (unaligned(reinterpret_cast(index), leftCoeff, rightCoeff, jump) && jump < alignedEnd) - _internals::snippetSaturatingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd); - - auto mmFloatIndex = _mm_set_ps1(floatIndex); - const auto mmLoopEnd = _mm_set1_ps(loopEnd); - const auto mmSaturated = _mm_sub_ps(mmLoopEnd, _mm_set_ps1(0.000001f)); - while (jump < alignedEnd) { - auto mmOffset = _mm_load_ps(jump); - mmOffset = _mm_add_ps(mmOffset, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOffset), 4))); - mmOffset = _mm_add_ps(mmOffset, _mm_shuffle_ps(_mm_setzero_ps(), mmOffset, 0x40)); - - mmFloatIndex = _mm_add_ps(mmFloatIndex, mmOffset); - const auto mmCompared = _mm_cmplt_ps(mmFloatIndex, mmLoopEnd); - mmFloatIndex = _mm_add_ps(_mm_and_ps(mmCompared, mmFloatIndex), _mm_andnot_ps(mmCompared, mmSaturated)); - - auto mmIndices = _mm_cvtps_epi32(_mm_sub_ps(mmFloatIndex, _mm_set_ps1(0.4999999552965164184570312f))); - _mm_store_si128(reinterpret_cast<__m128i*>(index), mmIndices); - - auto mmRight = _mm_sub_ps(mmFloatIndex, _mm_cvtepi32_ps(mmIndices)); - auto mmLeft = _mm_sub_ps(_mm_set_ps1(1.0f), mmRight); - _mm_store_ps(leftCoeff, mmLeft); - _mm_store_ps(rightCoeff, mmRight); - - mmFloatIndex = _mm_shuffle_ps(mmFloatIndex, mmFloatIndex, _MM_SHUFFLE(3, 3, 3, 3)); - // floatingIndex = _mm_cvtss_f32(_mm_shuffle_ps(mmFloatIndex, mmFloatIndex, _MM_SHUFFLE(0, 0, 0, 3)));; - // floatingIndex = *(index + 3) + *(rightCoeff + 3); - incrementAll(index, jump, leftCoeff, rightCoeff); - } - - floatIndex = _mm_cvtss_f32(mmFloatIndex); - while (jump < sentinel) - _internals::snippetSaturatingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd); - return floatIndex; -} - template <> float sfz::linearRamp(absl::Span output, float value, float step) noexcept { diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index 8bf3eed4..20b57866 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -342,105 +342,6 @@ TEST_CASE("[Helpers] Gain, spans and inplace (SIMD)") REQUIRE(buffer == expected); } -TEST_CASE("[Helpers] SFZ looping index") -{ - std::array jumps { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f }; // 1.1 2.3 3.6 5.0f 6.5 8.1 - std::array indices; - std::array leftCoeffs; - std::array rightCoeffs; - std::array expectedIndices { 2, 3, 4, 1, 2, 4 }; - std::array expectedLeft { 0.9f, 0.7f, 0.4f, 1.0f, 0.5f, 0.9f }; - std::array expectedRight { 0.1f, 0.3f, 0.6f, 0.0f, 0.5f, 0.1f }; - sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, 6, 1); - REQUIRE(indices == expectedIndices); - REQUIRE(approxEqual(leftCoeffs, expectedLeft)); - REQUIRE(approxEqual(rightCoeffs, expectedRight)); -} - -TEST_CASE("[Helpers] SFZ looping index (SIMD)") -{ - std::array jumps { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f }; // 1.1 2.3 3.6 5.0f 6.5 8.1 - std::array indices; - std::array leftCoeffs; - std::array rightCoeffs; - std::array expectedIndices { 2, 3, 4, 1, 2, 4 }; - std::array expectedLeft { 0.9f, 0.7f, 0.4f, 1.0f, 0.5f, 0.9f }; - std::array expectedRight { 0.1f, 0.3f, 0.6f, 0.0f, 0.5f, 0.1f }; - sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, 6, 1); - REQUIRE(indices == expectedIndices); - REQUIRE(approxEqual(leftCoeffs, expectedLeft)); - REQUIRE(approxEqual(rightCoeffs, expectedRight)); -} - -// TEST_CASE("[Helpers] SFZ looping index (SIMD vs Scalar)") -// { - -// std::vector jumps(bigBufferSize); -// absl::c_fill(jumps, fillValue); - -// std::vector indices(bigBufferSize); -// std::vector leftCoeffs(bigBufferSize); -// std::vector rightCoeffs(bigBufferSize); - -// std::vector indicesSIMD(bigBufferSize); -// std::vector leftCoeffsSIMD(bigBufferSize); -// std::vector rightCoeffsSIMD(bigBufferSize); -// sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, medBufferSize, 1); -// sfz::loopingSFZIndex(jumps, absl::MakeSpan(leftCoeffsSIMD), absl::MakeSpan(rightCoeffsSIMD), absl::MakeSpan(indicesSIMD), 1.0f, medBufferSize, 1); -// for (int i = 0; i < bigBufferSize; ++i) -// REQUIRE( ((static_cast(indices[i]) + rightCoeffs[i] == Approx(static_cast(indicesSIMD[i]) + rightCoeffsSIMD[i]).margin(1e-2)) -// || (static_cast(indices[i]) + rightCoeffs[i] == Approx(static_cast(indicesSIMD[i]) + rightCoeffsSIMD[i] - static_cast(medBufferSize)).margin(2e-2))) ); -// } - -TEST_CASE("[Helpers] SFZ saturating index") -{ - std::array jumps { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f }; // 1.1 2.3 3.6 5.0f 6.5 8.1 - std::array indices; - std::array leftCoeffs; - std::array rightCoeffs; - std::array expectedIndices { 2, 3, 4, 5, 5, 5 }; - std::array expectedLeft { 0.9f, 0.7f, 0.4f, 0.0f, 0.0f, 0.0f }; - std::array expectedRight { 0.1f, 0.3f, 0.6f, 1.0f, 1.0f, 1.0f }; - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, 6); - REQUIRE(indices == expectedIndices); - REQUIRE(approxEqual(leftCoeffs, expectedLeft)); - REQUIRE(approxEqual(rightCoeffs, expectedRight)); -} - -TEST_CASE("[Helpers] SFZ saturating index (SIMD)") -{ - std::array jumps { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f }; // 1.1 2.3 3.6 5.0f 6.5 8.1 - std::array indices; - std::array leftCoeffs; - std::array rightCoeffs; - std::array expectedIndices { 2, 3, 4, 5, 5, 5 }; - std::array expectedLeft { 0.9f, 0.7f, 0.4f, 0.0f, 0.0f, 0.0f }; - std::array expectedRight { 0.1f, 0.3f, 0.6f, 1.0f, 1.0f, 1.0f }; - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, 6); - REQUIRE(indices == expectedIndices); - REQUIRE(approxEqualMargin(leftCoeffs, expectedLeft)); - REQUIRE(approxEqualMargin(rightCoeffs, expectedRight)); -} - -TEST_CASE("[Helpers] SFZ saturating index (SIMD vs Scalar)") -{ - - std::vector jumps(medBufferSize); - absl::c_fill(jumps, fillValue); - - std::vector indices(medBufferSize); - std::vector leftCoeffs(medBufferSize); - std::vector rightCoeffs(medBufferSize); - - std::vector indicesSIMD(medBufferSize); - std::vector leftCoeffsSIMD(medBufferSize); - std::vector rightCoeffsSIMD(medBufferSize); - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs), absl::MakeSpan(indices), 1.0f, 78); - sfz::saturatingSFZIndex(jumps, absl::MakeSpan(leftCoeffsSIMD), absl::MakeSpan(rightCoeffsSIMD), absl::MakeSpan(indicesSIMD), 1.0f, 78); - for (int i = 0; i < medBufferSize; ++i) - REQUIRE( static_cast(indices[i]) + rightCoeffs[i] == Approx(static_cast(indicesSIMD[i]) + rightCoeffsSIMD[i])); -} - TEST_CASE("[Helpers] Linear Ramp") { const float start { 0.0f };