Interpolators with simde

This commit is contained in:
Jean Pierre Cimalando 2021-02-16 00:25:57 +01:00
parent a338ec7368
commit d7b9dc2285
4 changed files with 68 additions and 60 deletions

View file

@ -252,7 +252,7 @@ add_library(sfizz::internal ALIAS sfizz_internal)
target_sources(sfizz_internal PRIVATE ${SFIZZ_HEADERS} ${SFIZZ_SOURCES} ${FAUST_FILES})
target_include_directories(sfizz_internal PUBLIC "." "sfizz")
target_link_libraries(sfizz_internal
PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex
PUBLIC absl::strings absl::span sfizz::filesystem sfizz::atomic_queue sfizz::spin_mutex sfizz::simde
PRIVATE sfizz::parser sfizz::messaging absl::flat_hash_map Threads::Threads st_audiofile sfizz::pugixml sfizz::spline sfizz::tunings sfizz::hiir sfizz::kissfft sfizz::cephes sfizz::cpuid sfizz::threadpool sfizz::jsl sfizz::atomic)
if(SFIZZ_USE_SNDFILE)
target_compile_definitions(sfizz_internal PUBLIC "SFIZZ_USE_SNDFILE=1")

View file

@ -8,6 +8,10 @@
#include "WindowedSinc.h"
#include "MathHelpers.h"
#include "SIMDConfig.h"
#include <simde/simde-features.h>
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
#include <simde/x86/sse.h>
#endif
namespace sfz {
@ -49,25 +53,25 @@ public:
//------------------------------------------------------------------------------
// Hermite 3rd order, SSE specialization
#if SFIZZ_HAVE_SSE
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
template <>
class Interpolator<kInterpolatorHermite3, float>
{
public:
static inline float process(const float* values, float coeff)
{
__m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff));
__m128 h = hermite3x4(x);
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1));
simde__m128 x = simde_mm_sub_ps(simde_mm_setr_ps(-1, 0, 1, 2), simde_mm_set1_ps(coeff));
simde__m128 h = hermite3x4(x);
simde__m128 y = simde_mm_mul_ps(h, simde_mm_loadu_ps(values - 1));
// sum 4 to 1
__m128 xmm0 = y;
__m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5);
__m128 xmm2 = _mm_movehl_ps(xmm0, xmm0);
xmm1 = _mm_add_ss(xmm1, xmm0);
xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = _mm_add_ss(xmm2, xmm1);
xmm0 = _mm_add_ss(xmm0, xmm2);
return _mm_cvtss_f32(xmm0);
simde__m128 xmm0 = y;
simde__m128 xmm1 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe5);
simde__m128 xmm2 = simde_mm_movehl_ps(xmm0, xmm0);
xmm1 = simde_mm_add_ss(xmm1, xmm0);
xmm0 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = simde_mm_add_ss(xmm2, xmm1);
xmm0 = simde_mm_add_ss(xmm0, xmm2);
return simde_mm_cvtss_f32(xmm0);
}
};
#endif
@ -93,25 +97,25 @@ public:
//------------------------------------------------------------------------------
// B-spline 3rd order, SSE specialization
#if SFIZZ_HAVE_SSE
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
template <>
class Interpolator<kInterpolatorBspline3, float>
{
public:
static inline float process(const float* values, float coeff)
{
__m128 x = _mm_sub_ps(_mm_setr_ps(-1, 0, 1, 2), _mm_set1_ps(coeff));
__m128 h = bspline3x4(x);
__m128 y = _mm_mul_ps(h, _mm_loadu_ps(values - 1));
simde__m128 x = simde_mm_sub_ps(simde_mm_setr_ps(-1, 0, 1, 2), simde_mm_set1_ps(coeff));
simde__m128 h = bspline3x4(x);
simde__m128 y = simde_mm_mul_ps(h, simde_mm_loadu_ps(values - 1));
// sum 4 to 1
__m128 xmm0 = y;
__m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5);
__m128 xmm2 = _mm_movehl_ps(xmm0, xmm0);
xmm1 = _mm_add_ss(xmm1, xmm0);
xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = _mm_add_ss(xmm2, xmm1);
xmm0 = _mm_add_ss(xmm0, xmm2);
return _mm_cvtss_f32(xmm0);
simde__m128 xmm0 = y;
simde__m128 xmm1 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe5);
simde__m128 xmm2 = simde_mm_movehl_ps(xmm0, xmm0);
xmm1 = simde_mm_add_ss(xmm1, xmm0);
xmm0 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = simde_mm_add_ss(xmm2, xmm1);
xmm0 = simde_mm_add_ss(xmm0, xmm2);
return simde_mm_cvtss_f32(xmm0);
}
};
#endif
@ -190,7 +194,7 @@ class SincInterpolator;
//------------------------------------------------------------------------------
// Windowed sinc any order, SSE specialization
#if SFIZZ_HAVE_SSE2
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
template <size_t Points>
class SincInterpolator<float, Points>
{
@ -204,25 +208,25 @@ public:
constexpr int j0 = 1 - int(Points) / 2;
float x0 = j0 - coeff;
__m128 y = _mm_set1_ps(0.0f);
__m128 x = _mm_add_ps(_mm_set1_ps(x0), _mm_setr_ps(0, 1, 2, 3));
simde__m128 y = simde_mm_set1_ps(0.0f);
simde__m128 x = simde_mm_add_ps(simde_mm_set1_ps(x0), simde_mm_setr_ps(0, 1, 2, 3));
size_t i = 0;
do {
__m128 h = ws.getUncheckedX4(x);
y = _mm_add_ps(y, _mm_mul_ps(h, _mm_loadu_ps(&values[j0 + i])));
x = _mm_add_ps(x, _mm_set1_ps(4.0f));
simde__m128 h = ws.getUncheckedX4(x);
y = simde_mm_add_ps(y, simde_mm_mul_ps(h, simde_mm_loadu_ps(&values[j0 + i])));
x = simde_mm_add_ps(x, simde_mm_set1_ps(4.0f));
i += 4;
} while (i < Points);
// sum 4 to 1
__m128 xmm0 = y;
__m128 xmm1 = _mm_shuffle_ps(xmm0, xmm0, 0xe5);
__m128 xmm2 = _mm_movehl_ps(xmm0, xmm0);
xmm1 = _mm_add_ss(xmm1, xmm0);
xmm0 = _mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = _mm_add_ss(xmm2, xmm1);
xmm0 = _mm_add_ss(xmm0, xmm2);
return _mm_cvtss_f32(xmm0);
simde__m128 xmm0 = y;
simde__m128 xmm1 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe5);
simde__m128 xmm2 = simde_mm_movehl_ps(xmm0, xmm0);
xmm1 = simde_mm_add_ss(xmm1, xmm0);
xmm0 = simde_mm_shuffle_ps(xmm0, xmm0, 0xe7);
xmm2 = simde_mm_add_ss(xmm2, xmm1);
xmm0 = simde_mm_add_ss(xmm0, xmm2);
return simde_mm_cvtss_f32(xmm0);
}
};
#endif

View file

@ -8,8 +8,9 @@
#include "SIMDConfig.h"
#include <absl/types/span.h>
#include <memory>
#if SFIZZ_HAVE_SSE2
#include <xmmintrin.h>
#include <simde/simde-features.h>
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
#include <simde/x86/sse.h>
#endif
namespace sfz {
@ -30,9 +31,9 @@ public:
// interpolate f(x), where x must be in domain [-Points/2:+Points/2]
float getUnchecked(float x) const noexcept;
#if SFIZZ_HAVE_SSE2
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
// interpolate f(x), 4 values at once
__m128 getUncheckedX4(__m128 x) const noexcept;
simde__m128 getUncheckedX4(simde__m128 x) const noexcept;
#endif
// calculate exact f(x), where x must be in domain [-Points/2:+Points/2]

View file

@ -7,6 +7,9 @@
#pragma once
#include "WindowedSinc.h"
#include <cstdint>
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
#include <simde/x86/sse2.h>
#endif
namespace sfz {
@ -36,33 +39,33 @@ inline float AbstractWindowedSinc<T>::getUnchecked(float x) const noexcept
return y0 + mu * dy;
}
#if SFIZZ_HAVE_SSE2
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
template <class T>
inline __m128 AbstractWindowedSinc<T>::getUncheckedX4(__m128 x) const noexcept
inline simde__m128 AbstractWindowedSinc<T>::getUncheckedX4(simde__m128 x) const noexcept
{
const float* table = static_cast<const T*>(this)->getTablePointer();
size_t points = static_cast<const T*>(this)->getNumPoints();
size_t tableSize = static_cast<const T*>(this)->getTableSize();
__m128 ix = _mm_mul_ps(
_mm_add_ps(x, _mm_set1_ps(points / 2.0f)),
_mm_set1_ps((tableSize - 1) / points));
alignas(__m128i) int j0[4];
__m128i i0 = _mm_cvttps_epi32(ix);
_mm_store_si128((__m128i*)j0, i0);
__m128 mu = _mm_sub_ps(ix, _mm_cvtepi32_ps(i0));
simde__m128 ix = simde_mm_mul_ps(
simde_mm_add_ps(x, simde_mm_set1_ps(points / 2.0f)),
simde_mm_set1_ps((tableSize - 1) / points));
alignas(simde__m128i) int j0[4];
simde__m128i i0 = simde_mm_cvttps_epi32(ix);
simde_mm_store_si128((simde__m128i*)j0, i0);
simde__m128 mu = simde_mm_sub_ps(ix, simde_mm_cvtepi32_ps(i0));
// reference: Interpolated table lookups using SSE2 [2/2]
// https://rawstudio.org/blog/?p=482
__m128 p0p1 = _mm_castsi128_ps(_mm_loadl_epi64((__m128i*)&table[j0[0]]));
__m128 p2p3 = _mm_castsi128_ps(_mm_loadl_epi64((__m128i*)&table[j0[2]]));
p0p1 = _mm_loadh_pi(p0p1, (__m64*)&table[j0[1]]);
p2p3 = _mm_loadh_pi(p2p3, (__m64*)&table[j0[3]]);
__m128 y0 = _mm_shuffle_ps(p0p1, p2p3, _MM_SHUFFLE(2, 0, 2, 0));
__m128 y1 = _mm_shuffle_ps(p0p1, p2p3, _MM_SHUFFLE(3, 1, 3, 1));
simde__m128 p0p1 = simde_mm_castsi128_ps(simde_mm_loadl_epi64((simde__m128i*)&table[j0[0]]));
simde__m128 p2p3 = simde_mm_castsi128_ps(simde_mm_loadl_epi64((simde__m128i*)&table[j0[2]]));
p0p1 = simde_mm_loadh_pi(p0p1, (simde__m64*)&table[j0[1]]);
p2p3 = simde_mm_loadh_pi(p2p3, (simde__m64*)&table[j0[3]]);
simde__m128 y0 = simde_mm_shuffle_ps(p0p1, p2p3, SIMDE_MM_SHUFFLE(2, 0, 2, 0));
simde__m128 y1 = simde_mm_shuffle_ps(p0p1, p2p3, SIMDE_MM_SHUFFLE(3, 1, 3, 1));
__m128 dy = _mm_sub_ps(y1, y0);
return _mm_add_ps(y0, _mm_mul_ps(mu, dy));
simde__m128 dy = simde_mm_sub_ps(y1, y0);
return simde_mm_add_ps(y0, simde_mm_mul_ps(mu, dy));
}
#endif