Merge pull request #561 from jpcima/simde

Interpolation using simde
This commit is contained in:
JP Cimalando 2021-02-22 00:08:50 +01:00 committed by GitHub
commit 5bbbe3d491
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 112 additions and 94 deletions

3
.gitmodules vendored
View file

@ -39,3 +39,6 @@
path = external/filesystem
url = https://github.com/gulrak/filesystem.git
shallow = true
[submodule "external/simde"]
path = external/simde
url = https://github.com/sfztools/simde.git

View file

@ -1,6 +1,16 @@
# Find system threads
find_package(Threads REQUIRED)
# Find OpenMP
find_package(OpenMP)
if(OPENMP_FOUND)
add_library(sfizz_openmp INTERFACE)
add_library(sfizz::openmp ALIAS sfizz_openmp)
target_compile_options(sfizz_openmp INTERFACE
$<$<COMPILE_LANGUAGE:C>:${OpenMP_C_FLAGS}>
$<$<COMPILE_LANGUAGE:CXX>:${OpenMP_CXX_FLAGS}>)
endif()
# Find macOS system libraries
if(APPLE)
find_library(APPLE_COREFOUNDATION_LIBRARY "CoreFoundation")
@ -67,6 +77,14 @@ else()
endif()
add_subdirectory("external/st_audiofile" EXCLUDE_FROM_ALL)
# The simde library
add_library(sfizz_simde INTERFACE)
add_library(sfizz::simde ALIAS sfizz_simde)
target_include_directories(sfizz_simde INTERFACE "external/simde")
if(TARGET sfizz::openmp)
target_link_libraries(sfizz_simde INTERFACE sfizz::openmp)
endif()
# The pugixml library
add_library(sfizz_pugixml STATIC "src/external/pugixml/src/pugixml.cpp")
add_library(sfizz::pugixml ALIAS sfizz_pugixml)

View file

@ -315,6 +315,10 @@ SFIZZ_SOURCES += \
src/external/cpuid/src/cpuid/cpuinfo.cpp \
src/external/cpuid/src/cpuid/version.cpp
### simde dependency
SFIZZ_C_FLAGS += \
-I$(SFIZZ_DIR)/external/simde
### Pugixml dependency
SFIZZ_C_FLAGS += -I$(SFIZZ_DIR)/src/external/pugixml/src
@ -360,3 +364,9 @@ SFIZZ_C_FLAGS += -pthread
SFIZZ_CXX_FLAGS += -pthread
SFIZZ_LINK_FLAGS += -pthread
endif
### OpenMP dependency
SFIZZ_C_FLAGS += -fopenmp
SFIZZ_CXX_FLAGS += -fopenmp
SFIZZ_LINK_FLAGS += -fopenmp

1
external/simde vendored Submodule

@ -0,0 +1 @@
Subproject commit 0ba9d8fdc0569e5a887dc42c6ddfa2a27a9f6867

View file

@ -30,7 +30,7 @@ clang-tidy \
vst/SfizzVstState.cpp \
-- -Iexternal/abseil-cpp -Iexternal/jsl/include -Iexternal/filesystem/include -Iexternal/atomic_queue/include -Iexternal/threadpool -Isrc/external/hiir -Isrc/external/pugixml/src \
-Iexternal/st_audiofile/src -Iexternal/st_audiofile/thirdparty/dr_libs \
-Isrc/sfizz -Isrc -Isrc/sfizz/utility/spin_mutex -Isrc/external/spline -Isrc/external/cpuid/src \
-Isrc/sfizz -Isrc -Isrc/sfizz/utility/spin_mutex -Isrc/external/spline -Isrc/external/cpuid/src -Iexternal/simde \
-Ivst -Ivst/external/VST_SDK/VST3_SDK -Ieditor/external/vstgui4 -Ivst/external/ring_buffer \
-Ieditor/src \
-DNDEBUG -std=c++17

View file

@ -217,7 +217,7 @@ target_sources(sfizz_parser PRIVATE
${SFIZZ_PARSER_HEADERS} ${SFIZZ_PARSER_SOURCES} ${SFIZZ_PARSER_OTHER})
target_include_directories(sfizz_parser PUBLIC sfizz)
target_link_libraries(sfizz_parser
PUBLIC sfizz::filesystem absl::strings
PUBLIC sfizz::filesystem sfizz::simde absl::strings
PRIVATE absl::flat_hash_map)
# OSC messaging library
@ -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,11 @@
#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>
#include <simde/arm/neon/addv.h>
#endif
namespace sfz {
@ -49,25 +54,17 @@ 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));
// 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 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));
return simde_vaddvq_f32(y);
}
};
#endif
@ -93,25 +90,17 @@ 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));
// 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 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));
return simde_vaddvq_f32(y);
}
};
#endif
@ -190,7 +179,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 +193,17 @@ 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);
return simde_vaddvq_f32(y);
}
};
#endif

View file

@ -21,8 +21,9 @@
#include <type_traits>
#include <cmath>
#include <cfenv>
#if SFIZZ_HAVE_SSE
#include <xmmintrin.h>
#include <simde/simde-features.h>
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
#include <simde/x86/sse.h>
#endif
#if __cplusplus >= 201703L
@ -195,26 +196,26 @@ R hermite3(R x)
return y;
}
#if SFIZZ_HAVE_SSE
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
/**
* @brief Compute 4 parallel elements of the 3rd-order Hermite interpolation polynomial.
*
* @param x
* @return __m128
* @return simde__m128
*/
inline __m128 hermite3x4(__m128 x)
inline simde__m128 hermite3x4(simde__m128 x)
{
x = _mm_andnot_ps(_mm_set1_ps(-0.0f), x);
__m128 x2 = _mm_mul_ps(x, x);
__m128 x3 = _mm_mul_ps(x2, x);
__m128 y = _mm_set1_ps(0.0f);
__m128 q = _mm_mul_ps(_mm_set1_ps(5./2.), x2);
__m128 p1 = _mm_add_ps(_mm_sub_ps(_mm_set1_ps(1), q), _mm_mul_ps(_mm_set1_ps(3./2.), x3));
__m128 p2 = _mm_sub_ps(_mm_add_ps(_mm_sub_ps(_mm_set1_ps(2), _mm_mul_ps(_mm_set1_ps(4), x)), q), _mm_mul_ps(_mm_set1_ps(1./2.), x3));
__m128 m2 = _mm_cmple_ps(x, _mm_set1_ps(2));
y = _mm_or_ps(_mm_and_ps(m2, p2), _mm_andnot_ps(m2, y));
__m128 m1 = _mm_cmple_ps(x, _mm_set1_ps(1));
y = _mm_or_ps(_mm_and_ps(m1, p1), _mm_andnot_ps(m1, y));
x = simde_x_mm_abs_ps(x);
simde__m128 x2 = simde_mm_mul_ps(x, x);
simde__m128 x3 = simde_mm_mul_ps(x2, x);
simde__m128 y = simde_mm_set1_ps(0.0f);
simde__m128 q = simde_mm_mul_ps(simde_mm_set1_ps(5./2.), x2);
simde__m128 p1 = simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(1), q), simde_mm_mul_ps(simde_mm_set1_ps(3./2.), x3));
simde__m128 p2 = simde_mm_sub_ps(simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(2), simde_mm_mul_ps(simde_mm_set1_ps(4), x)), q), simde_mm_mul_ps(simde_mm_set1_ps(1./2.), x3));
simde__m128 m2 = simde_mm_cmple_ps(x, simde_mm_set1_ps(2));
y = simde_mm_or_ps(simde_mm_and_ps(m2, p2), simde_mm_andnot_ps(m2, y));
simde__m128 m1 = simde_mm_cmple_ps(x, simde_mm_set1_ps(1));
y = simde_mm_or_ps(simde_mm_and_ps(m1, p1), simde_mm_andnot_ps(m1, y));
return y;
}
#endif
@ -240,25 +241,25 @@ R bspline3(R x)
return y;
}
#if SFIZZ_HAVE_SSE
#if SIMDE_NATURAL_VECTOR_SIZE_GE(128)
/**
* @brief Compute 4 parallel elements of the 3rd-order B-spline interpolation polynomial.
*
* @param x
* @return __m128
* @return simde__m128
*/
inline __m128 bspline3x4(__m128 x)
inline simde__m128 bspline3x4(simde__m128 x)
{
x = _mm_andnot_ps(_mm_set1_ps(-0.0f), x);
__m128 x2 = _mm_mul_ps(x, x);
__m128 x3 = _mm_mul_ps(x2, x);
__m128 y = _mm_set1_ps(0.0f);
__m128 p1 = _mm_add_ps(_mm_sub_ps(_mm_set1_ps(2./3.), x2), _mm_mul_ps(_mm_set1_ps(1./2.), x3));
__m128 p2 = _mm_sub_ps(_mm_add_ps(_mm_sub_ps(_mm_set1_ps(4./3.), _mm_mul_ps(_mm_set1_ps(2), x)), x2), _mm_mul_ps(_mm_set1_ps(1./6.), x3));
__m128 m2 = _mm_cmple_ps(x, _mm_set1_ps(2));
y = _mm_or_ps(_mm_and_ps(m2, p2), _mm_andnot_ps(m2, y));
__m128 m1 = _mm_cmple_ps(x, _mm_set1_ps(1));
y = _mm_or_ps(_mm_and_ps(m1, p1), _mm_andnot_ps(m1, y));
x = simde_x_mm_abs_ps(x);
simde__m128 x2 = simde_mm_mul_ps(x, x);
simde__m128 x3 = simde_mm_mul_ps(x2, x);
simde__m128 y = simde_mm_set1_ps(0.0f);
simde__m128 p1 = simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(2./3.), x2), simde_mm_mul_ps(simde_mm_set1_ps(1./2.), x3));
simde__m128 p2 = simde_mm_sub_ps(simde_mm_add_ps(simde_mm_sub_ps(simde_mm_set1_ps(4./3.), simde_mm_mul_ps(simde_mm_set1_ps(2), x)), x2), simde_mm_mul_ps(simde_mm_set1_ps(1./6.), x3));
simde__m128 m2 = simde_mm_cmple_ps(x, simde_mm_set1_ps(2));
y = simde_mm_or_ps(simde_mm_and_ps(m2, p2), simde_mm_andnot_ps(m2, y));
simde__m128 m1 = simde_mm_cmple_ps(x, simde_mm_set1_ps(1));
y = simde_mm_or_ps(simde_mm_and_ps(m1, p1), simde_mm_andnot_ps(m1, y));
return y;
}
#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