Accelerate windowed sinc SSE2
This commit is contained in:
parent
0629a6b30d
commit
c7a75ee2fc
3 changed files with 53 additions and 11 deletions
|
|
@ -190,7 +190,7 @@ class SincInterpolator;
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
// Windowed sinc any order, SSE specialization
|
||||
#if SFIZZ_HAVE_SSE
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
template <size_t Points>
|
||||
class SincInterpolator<float, Points>
|
||||
{
|
||||
|
|
@ -201,15 +201,18 @@ public:
|
|||
{
|
||||
const auto &ws = *SincInterpolatorTraits<Points>::windowedSinc;
|
||||
|
||||
int j0 = 1 - int(Points) / 2;
|
||||
constexpr int j0 = 1 - int(Points) / 2;
|
||||
float x0 = j0 - coeff;
|
||||
|
||||
__m128 h[Points / 4];
|
||||
for (int i = 0; i < int(Points); ++i)
|
||||
reinterpret_cast<float*>(h)[i] = ws.getUnchecked(j0 - coeff + i);
|
||||
|
||||
__m128 y = _mm_mul_ps(h[0], _mm_loadu_ps(&values[j0]));
|
||||
for (int i = 1; i < int(Points / 4); ++i)
|
||||
y = _mm_add_ps(y, _mm_mul_ps(h[i], _mm_loadu_ps(&values[j0 + 4 * i])));
|
||||
__m128 y = _mm_set1_ps(0.0f);
|
||||
__m128 x = _mm_add_ps(_mm_set1_ps(x0), _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));
|
||||
i += 4;
|
||||
} while (i < Points);
|
||||
|
||||
// sum 4 to 1
|
||||
__m128 xmm0 = y;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@
|
|||
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
|
||||
|
||||
#pragma once
|
||||
#include "SIMDConfig.h"
|
||||
#include <absl/types/span.h>
|
||||
#include <memory>
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
namespace sfz {
|
||||
|
||||
|
|
@ -26,6 +30,11 @@ public:
|
|||
// interpolate f(x), where x must be in domain [-Points/2:+Points/2]
|
||||
float getUnchecked(float x) const noexcept;
|
||||
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
// interpolate f(x), 4 values at once
|
||||
__m128 getUncheckedX4(__m128 x) const noexcept;
|
||||
#endif
|
||||
|
||||
// calculate exact f(x), where x must be in domain [-Points/2:+Points/2]
|
||||
double getExact(double x) const noexcept;
|
||||
|
||||
|
|
@ -35,8 +44,8 @@ public:
|
|||
protected:
|
||||
void fillTable() noexcept;
|
||||
|
||||
// allows interpolating f(Points/2), provided for safety
|
||||
enum { TableExtra = 1 };
|
||||
// allows interpolating f(Points/2), and SSE, provided for safety
|
||||
enum { TableExtra = 4 };
|
||||
|
||||
private:
|
||||
double beta_ {};
|
||||
|
|
|
|||
|
|
@ -36,6 +36,36 @@ inline float AbstractWindowedSinc<T>::getUnchecked(float x) const noexcept
|
|||
return y0 + mu * dy;
|
||||
}
|
||||
|
||||
#if SFIZZ_HAVE_SSE2
|
||||
template <class T>
|
||||
inline __m128 AbstractWindowedSinc<T>::getUncheckedX4(__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));
|
||||
|
||||
// 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));
|
||||
|
||||
__m128 dy = _mm_sub_ps(y1, y0);
|
||||
return _mm_add_ps(y0, _mm_mul_ps(mu, dy));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
inline double AbstractWindowedSinc<T>::getExact(double x) const noexcept
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue