Corrected an error when activating the SIMD extension on HIIR

This commit is contained in:
Paul Ferrand 2019-12-04 01:18:59 +01:00
parent 0efbf96b4a
commit e2ce30c104
14 changed files with 607 additions and 749 deletions

View file

@ -1,174 +0,0 @@
/*****************************************************************************
StageProc4Neon.hpp
Author: Laurent de Soras, 2016
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#if ! defined (hiir_StageProc4Neon_CODEHEADER_INCLUDED)
#define hiir_StageProc4Neon_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataNeon.h"
namespace hiir
{
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
template <>
inline void StageProc4Neon <1>::process_sample_pos (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2 - 1;
const float32x4_t tmp_0 = vmlaq_f32 (
stage_arr [cnt - 2]._mem4,
spl_0 - stage_arr [cnt ]._mem4,
stage_arr [cnt ]._coef4
);
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
stage_arr [cnt ]._mem4 = tmp_0;
spl_0 = tmp_0;
}
template <>
inline void StageProc4Neon <0>::process_sample_pos (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2;
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
}
template <int REMAINING>
void StageProc4Neon <REMAINING>::process_sample_pos (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2 - REMAINING;
const float32x4_t tmp_0 = vmlaq_f32 (
stage_arr [cnt - 2]._mem4,
spl_0 - stage_arr [cnt ]._mem4,
stage_arr [cnt ]._coef4
);
const float32x4_t tmp_1 = vmlaq_f32 (
stage_arr [cnt - 1]._mem4,
spl_1 - stage_arr [cnt + 1]._mem4,
stage_arr [cnt + 1]._coef4
);
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
spl_0 = tmp_0;
spl_1 = tmp_1;
StageProc4Neon <REMAINING - 2>::process_sample_pos (
nbr_coefs,
spl_0,
spl_1,
stage_arr
);
}
template <>
inline void StageProc4Neon <1>::process_sample_neg (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2 - 1;
float32x4_t tmp_0 = spl_0;
tmp_0 += stage_arr [cnt ]._mem4;
tmp_0 *= stage_arr [cnt ]._coef4;
tmp_0 -= stage_arr [cnt - 2]._mem4;
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
stage_arr [cnt ]._mem4 = tmp_0;
spl_0 = tmp_0;
}
template <>
inline void StageProc4Neon <0>::process_sample_neg (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2;
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
}
template <int REMAINING>
void StageProc4Neon <REMAINING>::process_sample_neg (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr)
{
const int cnt = nbr_coefs + 2 - REMAINING;
float32x4_t tmp_0 = spl_0;
tmp_0 += stage_arr [cnt ]._mem4;
tmp_0 *= stage_arr [cnt ]._coef4;
tmp_0 -= stage_arr [cnt - 2]._mem4;
float32x4_t tmp_1 = spl_1;
tmp_1 += stage_arr [cnt + 1]._mem4;
tmp_1 *= stage_arr [cnt + 1]._coef4;
tmp_1 -= stage_arr [cnt - 1]._mem4;
stage_arr [cnt - 2]._mem4 = spl_0;
stage_arr [cnt - 1]._mem4 = spl_1;
spl_0 = tmp_0;
spl_1 = tmp_1;
StageProc4Neon <REMAINING - 2>::process_sample_neg (
nbr_coefs,
spl_0,
spl_1,
stage_arr
);
}
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
} // namespace hiir
#endif // hiir_StageProc4Neon_CODEHEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,205 +0,0 @@
/*****************************************************************************
StageProc4Sse.hpp
Author: Laurent de Soras, 2015
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#if defined (hiir_StageProc4Sse_CURRENT_CODEHEADER)
#error Recursive inclusion of StageProc4Sse code header.
#endif
#define hiir_StageProc4Sse_CURRENT_CODEHEADER
#if ! defined (hiir_StageProc4Sse_CODEHEADER_INCLUDED)
#define hiir_StageProc4Sse_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataSse.h"
#if defined (_MSC_VER)
#pragma inline_depth (255)
#endif
namespace hiir
{
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
template <>
hiir_FORCEINLINE void StageProc4Sse <1>::process_sample_pos (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2 - 1;
const __m128 tmp_0 = _mm_add_ps (
_mm_mul_ps (
_mm_sub_ps (spl_0, _mm_load_ps (stage_arr [cnt ]._mem)),
_mm_load_ps (stage_arr [cnt ]._coef)
),
_mm_load_ps (stage_arr [cnt - 2]._mem)
);
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
_mm_store_ps (stage_arr [cnt ]._mem, tmp_0);
spl_0 = tmp_0;
}
template <>
hiir_FORCEINLINE void StageProc4Sse <0>::process_sample_pos (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2;
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
}
template <int REMAINING>
void StageProc4Sse <REMAINING>::process_sample_pos (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2 - REMAINING;
const __m128 tmp_0 = _mm_add_ps (
_mm_mul_ps (
_mm_sub_ps (spl_0, _mm_load_ps (stage_arr [cnt ]._mem)),
_mm_load_ps (stage_arr [cnt ]._coef)
),
_mm_load_ps (stage_arr [cnt - 2]._mem)
);
const __m128 tmp_1 = _mm_add_ps (
_mm_mul_ps (
_mm_sub_ps (spl_1, _mm_load_ps (stage_arr [cnt + 1]._mem)),
_mm_load_ps (stage_arr [cnt + 1]._coef)
),
_mm_load_ps (stage_arr [cnt - 1]._mem)
);
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
spl_0 = tmp_0;
spl_1 = tmp_1;
StageProc4Sse <REMAINING - 2>::process_sample_pos (
nbr_coefs,
spl_0,
spl_1,
stage_arr
);
}
template <>
hiir_FORCEINLINE void StageProc4Sse <1>::process_sample_neg (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2 - 1;
const __m128 tmp_0 = _mm_sub_ps (
_mm_mul_ps (
_mm_add_ps (spl_0, _mm_load_ps (stage_arr [cnt ]._mem)),
_mm_load_ps (stage_arr [cnt ]._coef)
),
_mm_load_ps (stage_arr [cnt - 2]._mem)
);
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
_mm_store_ps (stage_arr [cnt ]._mem, tmp_0);
spl_0 = tmp_0;
}
template <>
hiir_FORCEINLINE void StageProc4Sse <0>::process_sample_neg (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2;
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
}
template <int REMAINING>
void StageProc4Sse <REMAINING>::process_sample_neg (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr)
{
const int cnt = nbr_coefs + 2 - REMAINING;
const __m128 tmp_0 = _mm_sub_ps (
_mm_mul_ps (
_mm_add_ps (spl_0, _mm_load_ps (stage_arr [cnt ]._mem)),
_mm_load_ps (stage_arr [cnt ]._coef)
),
_mm_load_ps (stage_arr [cnt - 2]._mem)
);
const __m128 tmp_1 = _mm_sub_ps (
_mm_mul_ps (
_mm_add_ps (spl_1, _mm_load_ps (stage_arr [cnt + 1]._mem)),
_mm_load_ps (stage_arr [cnt + 1]._coef)
),
_mm_load_ps (stage_arr [cnt - 1]._mem)
);
_mm_store_ps (stage_arr [cnt - 2]._mem, spl_0);
_mm_store_ps (stage_arr [cnt - 1]._mem, spl_1);
spl_0 = tmp_0;
spl_1 = tmp_1;
StageProc4Sse <REMAINING - 2>::process_sample_neg (
nbr_coefs,
spl_0,
spl_1,
stage_arr
);
}
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
} // namespace hiir
#endif // hiir_StageProc4Sse_CODEHEADER_INCLUDED
#undef hiir_StageProc4Sse_CURRENT_CODEHEADER
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,10 +1,10 @@
/***************************************************************************** /*****************************************************************************
StageProc4Neon.h StageProcNeon.h
Author: Laurent de Soras, 2016 Author: Laurent de Soras, 2016
Template parameters: Template parameters:
- REMAINING: Number of remaining coefficients to process, >= 0 - CUR: index of the coefficient coefficient to process, >= 0
--- Legal stuff --- --- Legal stuff ---
@ -19,8 +19,8 @@ http://sam.zoy.org/wtfpl/COPYING for more details.
#pragma once #pragma once
#if ! defined (hiir_StageProc4Neon_HEADER_INCLUDED) #if ! defined (hiir_StageProcNeon_HEADER_INCLUDED)
#define hiir_StageProc4Neon_HEADER_INCLUDED #define hiir_StageProcNeon_HEADER_INCLUDED
#if defined (_MSC_VER) #if defined (_MSC_VER)
#pragma warning (4 : 4250) #pragma warning (4 : 4250)
@ -41,19 +41,20 @@ namespace hiir
class StageDataNeon; class StageDataNeon;
template <int REMAINING> template <int CUR>
class StageProc4Neon class StageProcNeon
{ {
static_assert (REMAINING >= 0, "REMAINING must be >= 0.");
static_assert ((CUR >= 0), "CUR must be >= 0");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public: public:
static hiir_FORCEINLINE void static hiir_FORCEINLINE void
process_sample_pos (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr); process_sample_pos (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem);
static hiir_FORCEINLINE void static hiir_FORCEINLINE void
process_sample_neg (const int nbr_coefs, float32x4_t &spl_0, float32x4_t &spl_1, StageDataNeon *stage_arr); process_sample_neg (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem);
@ -67,21 +68,23 @@ protected:
private: private:
enum { PREV = CUR - 1 };
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private: private:
StageProc4Neon () = delete; StageProcNeon () = delete;
StageProc4Neon (const StageProc4Neon <REMAINING> &other) = delete; StageProcNeon (const StageProcNeon <CUR> &other) = delete;
~StageProc4Neon () = delete; ~StageProcNeon () = delete;
StageProc4Neon <REMAINING> & StageProcNeon &
operator = (const StageProc4Neon <REMAINING> &other) = delete; operator = (const StageProcNeon <CUR> &other) = delete;
bool operator == (const StageProc4Neon <REMAINING> &other) const = delete; bool operator == (const StageProcNeon <CUR> &other) const = delete;
bool operator != (const StageProc4Neon <REMAINING> &other) const = delete; bool operator != (const StageProcNeon <CUR> &other) const = delete;
}; // class StageProc4Neon }; // class StageProcNeon
@ -89,11 +92,11 @@ private:
#include "hiir/StageProc4Neon.hpp" #include "hiir/StageProcNeon.hpp"
#endif // hiir_StageProc4Neon_HEADER_INCLUDED #endif // hiir_StageProcNeon_HEADER_INCLUDED

96
src/external/hiir/StageProcNeon.hpp vendored Normal file
View file

@ -0,0 +1,96 @@
/*****************************************************************************
StageProcNeon.hpp
Author: Laurent de Soras, 2016
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#if ! defined (hiir_StageProcNeon_CODEHEADER_INCLUDED)
#define hiir_StageProcNeon_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataNeon.h"
namespace hiir
{
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
template <int CUR>
void StageProcNeon <CUR>::process_sample_pos (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem)
{
StageProcNeon <CUR - 1>::process_sample_pos (stage_ptr, y, mem);
const float32x4_t x = mem;
stage_ptr [PREV]._mem4 = y;
mem = stage_ptr [CUR]._mem4;
y = vmlaq_f32 (x, y - mem, stage_ptr [CUR]._coef4);
}
template <>
inline void StageProcNeon <0>::process_sample_pos (StageDataNeon * /* stage_ptr */, float32x4_t & /* y */, float32x4_t & /* mem */)
{
// Nothing, stops the recursion
}
template <int CUR>
void StageProcNeon <CUR>::process_sample_neg (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem)
{
StageProcNeon <CUR - 1>::process_sample_neg (stage_ptr, y, mem);
const float32x4_t x = mem;
stage_ptr [PREV]._mem4 = y;
mem = stage_ptr [CUR]._mem4;
y += mem;
y *= stage_ptr [CUR]._coef4;
y -= x;
}
template <>
inline void StageProcNeon <0>::process_sample_neg (StageDataNeon * /* stage_ptr */, float32x4_t & /* y */, float32x4_t & /* mem */)
{
// Nothing, stops the recursion
}
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
} // namespace hiir
#endif // hiir_StageProcNeon_CODEHEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,10 +1,10 @@
/***************************************************************************** /*****************************************************************************
StageProc4Sse.h StageProcSse.h
Author: Laurent de Soras, 2015 Author: Laurent de Soras, 2005
Template parameters: Template parameters:
- REMAINING: Number of remaining coefficients to process, >= 0 - CUR: index of the coefficient to process, >= 0
--- Legal stuff --- --- Legal stuff ---
@ -18,8 +18,8 @@ http://sam.zoy.org/wtfpl/COPYING for more details.
#if ! defined (hiir_StageProc4Sse_HEADER_INCLUDED) #if ! defined (hiir_StageProcSse_HEADER_INCLUDED)
#define hiir_StageProc4Sse_HEADER_INCLUDED #define hiir_StageProcSse_HEADER_INCLUDED
#if defined (_MSC_VER) #if defined (_MSC_VER)
#pragma once #pragma once
@ -43,20 +43,20 @@ namespace hiir
class StageDataSse; class StageDataSse;
template <int REMAINING> template <int CUR>
class StageProc4Sse class StageProcSse
{ {
static_assert ((REMAINING >= 0), "REMAINING must be >= 0"); static_assert ((CUR >= 0), "CUR must be >= 0");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public: public:
static hiir_FORCEINLINE void static hiir_FORCEINLINE void
process_sample_pos (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr); process_sample_pos (StageDataSse *stage_ptr, __m128 &y, __m128 &mem);
static hiir_FORCEINLINE void static hiir_FORCEINLINE void
process_sample_neg (const int nbr_coefs, __m128 &spl_0, __m128 &spl_1, StageDataSse *stage_arr); process_sample_neg (StageDataSse *stage_ptr, __m128 &y, __m128 &mem);
@ -70,20 +70,22 @@ protected:
private: private:
enum { PREV = CUR - 1 };
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private: private:
StageProc4Sse (); StageProcSse ();
StageProc4Sse (const StageProc4Sse <REMAINING> &other); StageProcSse (const StageProcSse <CUR> &other);
StageProc4Sse <REMAINING> & StageProcSse <CUR> &
operator = (const StageProc4Sse <REMAINING> &other); operator = (const StageProcSse <CUR> &other);
bool operator == (const StageProc4Sse <REMAINING> &other); bool operator == (const StageProcSse <CUR> &other);
bool operator != (const StageProc4Sse <REMAINING> &other); bool operator != (const StageProcSse <CUR> &other);
}; // class StageProc4Sse }; // class StageProcSse
@ -91,11 +93,11 @@ private:
#include "hiir/StageProc4Sse.hpp" #include "hiir/StageProcSse.hpp"
#endif // hiir_StageProc4Sse_HEADER_INCLUDED #endif // hiir_StageProcSse_HEADER_INCLUDED

111
src/external/hiir/StageProcSse.hpp vendored Normal file
View file

@ -0,0 +1,111 @@
/*****************************************************************************
StageProcSse.hpp
Author: Laurent de Soras, 2005
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#if defined (hiir_StageProcSse_CURRENT_CODEHEADER)
#error Recursive inclusion of StageProcSse code header.
#endif
#define hiir_StageProcSse_CURRENT_CODEHEADER
#if ! defined (hiir_StageProcSse_CODEHEADER_INCLUDED)
#define hiir_StageProcSse_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataSse.h"
#if defined (_MSC_VER)
#pragma inline_depth (255)
#endif
namespace hiir
{
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
template <int CUR>
void StageProcSse <CUR>::process_sample_pos (StageDataSse *stage_ptr, __m128 &y, __m128 &mem)
{
StageProcSse <CUR - 1>::process_sample_pos (stage_ptr, y, mem);
const __m128 x = mem;
_mm_store_ps (stage_ptr [PREV]._mem, y);
mem = _mm_load_ps (stage_ptr [CUR]._mem);
y = _mm_sub_ps (y, mem);
const __m128 coef = _mm_load_ps (stage_ptr [CUR]._coef);
y = _mm_mul_ps (y, coef);
y = _mm_add_ps (y, x);
}
template <>
hiir_FORCEINLINE void StageProcSse <0>::process_sample_pos (StageDataSse * /* stage_ptr */, __m128 & /* y */, __m128 & /* mem */)
{
// Nothing, stops the recursion
}
template <int CUR>
void StageProcSse <CUR>::process_sample_neg (StageDataSse *stage_ptr, __m128 &y, __m128 &mem)
{
StageProcSse <CUR - 1>::process_sample_neg (stage_ptr, y, mem);
const __m128 x = mem;
_mm_store_ps (stage_ptr [PREV]._mem, y);
mem = _mm_load_ps (stage_ptr [CUR]._mem);
y = _mm_add_ps (y, mem);
const __m128 coef = _mm_load_ps (stage_ptr [CUR]._coef);
y = _mm_mul_ps (y, coef);
y = _mm_sub_ps (y, x);
}
template <>
hiir_FORCEINLINE void StageProcSse <0>::process_sample_neg (StageDataSse * /* stage_ptr */, __m128 & /* y */, __m128 & /* mem */)
{
// Nothing, stops the recursion
}
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
} // namespace hiir
#endif // hiir_StageProcSse_CODEHEADER_INCLUDED
#undef hiir_StageProcSse_CURRENT_CODEHEADER
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,114 +0,0 @@
/*****************************************************************************
Upsampler2x4Neon.h
Author: Laurent de Soras, 2016
Upsamples vectors of 4 float by a factor 2 the input signal, using the NEON
instruction set.
This object must be aligned on a 16-byte boundary!
Template parameters:
- NC: number of coefficients, > 0
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#pragma once
#if ! defined (hiir_Upsampler2x4Neon_HEADER_INCLUDED)
#define hiir_Upsampler2x4Neon_HEADER_INCLUDED
#if defined (_MSC_VER)
#pragma warning (4 : 4250)
#endif
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/def.h"
#include "hiir/StageDataNeon.h"
#include <arm_neon.h>
#include <array>
namespace hiir
{
template <int NC>
class Upsampler2x4Neon
{
static_assert ((NC > 0), "Number of coefficient must be positive.");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public:
enum { NBR_COEFS = NC };
Upsampler2x4Neon ();
void set_coefs (const double coef_arr [NBR_COEFS]);
hiir_FORCEINLINE void
process_sample (float32x4_t &out_0, float32x4_t &out_1, float32x4_t input);
void process_block (float out_ptr [], const float in_ptr [], long nbr_spl);
void clear_buffers ();
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
protected:
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
typedef std::array <StageDataNeon, NBR_COEFS + 2> Filter; // Stages 0 and 1 contain only input memories
Filter _filter; // Should be the first member (thus easier to align)
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
bool operator == (const Upsampler2x4Neon <NC> &other) const = delete;
bool operator != (const Upsampler2x4Neon <NC> &other) const = delete;
}; // class Upsampler2x4Neon
} // namespace hiir
#include "hiir/Upsampler2x4Neon.hpp"
#endif // hiir_Upsampler2x4Neon_HEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,113 +0,0 @@
/*****************************************************************************
Upsampler2x4Sse.h
Author: Laurent de Soras, 2015
Upsamples vectors of 4 float by a factor 2 the input signal, using the SSE
instruction set.
This object must be aligned on a 16-byte boundary!
Template parameters:
- NC: number of coefficients, > 0
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#pragma once
#if ! defined (hiir_Upsampler2x4Sse_HEADER_INCLUDED)
#define hiir_Upsampler2x4Sse_HEADER_INCLUDED
#if defined (_MSC_VER)
#pragma warning (4 : 4250)
#endif
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/def.h"
#include "hiir/StageDataSse.h"
#include <xmmintrin.h>
#include <array>
namespace hiir
{
template <int NC>
class Upsampler2x4Sse
{
static_assert ((NC > 0), "Number of coefficient must be positive.");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public:
enum { NBR_COEFS = NC };
Upsampler2x4Sse ();
void set_coefs (const double coef_arr [NBR_COEFS]);
hiir_FORCEINLINE void
process_sample (__m128 &out_0, __m128 &out_1, __m128 input);
void process_block (float out_ptr [], const float in_ptr [], long nbr_spl);
void clear_buffers ();
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
protected:
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
typedef std::array <StageDataSse, NBR_COEFS + 2> Filter; // Stages 0 and 1 contain only input memories
Filter _filter; // Should be the first member (thus easier to align)
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
bool operator == (const Upsampler2x4Sse <NC> &other) const;
bool operator != (const Upsampler2x4Sse <NC> &other) const;
}; // class Upsampler2x4Sse
} // namespace hiir
#include "hiir/Upsampler2x4Sse.hpp"
#endif // hiir_Upsampler2x4Sse_HEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

117
src/external/hiir/Upsampler2xNeon.h vendored Normal file
View file

@ -0,0 +1,117 @@
/*****************************************************************************
Upsampler2xNeon.h
Author: Laurent de Soras, 2016
Upsamples by a factor 2 the input signal, using NEON instruction set.
This object must be aligned on a 16-byte boundary!
If the number of coefficients is 2 or 3 modulo 4, the output is delayed from
1 sample, compared to the theoretical formula (or FPU implementation).
Template parameters:
- NC: number of coefficients, > 0
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#pragma once
#if ! defined (hiir_Upsampler2xNeon_HEADER_INCLUDED)
#define hiir_Upsampler2xNeon_HEADER_INCLUDED
#if defined (_MSC_VER)
#pragma warning (4 : 4250)
#endif
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataNeon.h"
#include <array>
namespace hiir
{
template <int NC>
class Upsampler2xNeon
{
static_assert ((NC > 0), "Number of coefficient must be positive.");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public:
enum { NBR_COEFS = NC };
Upsampler2xNeon ();
Upsampler2xNeon (const Upsampler2xNeon &other) = default;
Upsampler2xNeon &
operator = (const Upsampler2xNeon &other) = default;
void set_coefs (const double coef_arr [NBR_COEFS]);
inline void process_sample (float &out_0, float &out_1, float input);
void process_block (float out_ptr [], const float in_ptr [], long nbr_spl);
void clear_buffers ();
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
protected:
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
enum { STAGE_WIDTH = 4 };
enum { NBR_STAGES = (NBR_COEFS + STAGE_WIDTH - 1) / STAGE_WIDTH };
typedef std::array <StageDataNeon, NBR_STAGES + 1> Filter; // Stage 0 contains only input memory
Filter _filter; // Should be the first member (thus easier to align)
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
bool operator == (const Upsampler2xNeon <NC> &other) const = delete;
bool operator != (const Upsampler2xNeon <NC> &other) const = delete;
}; // class Upsampler2xNeon
} // namespace hiir
#include "hiir/Upsampler2xNeon.hpp"
#endif // hiir_Upsampler2xNeon_HEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Upsampler2x4Neon.hpp Upsampler2xNeon.hpp
Author: Laurent de Soras, 2016 Author: Laurent de Soras, 2016
--- Legal stuff --- --- Legal stuff ---
@ -15,14 +15,16 @@ http://sam.zoy.org/wtfpl/COPYING for more details.
#if ! defined (hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED) #if ! defined (hiir_Upsampler2xNeon_CODEHEADER_INCLUDED)
#define hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED #define hiir_Upsampler2xNeon_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageProc4Neon.h" #include "hiir/StageProcNeon.h"
#include <arm_neon.h>
#include <cassert> #include <cassert>
@ -45,13 +47,18 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
Upsampler2x4Neon <NC>::Upsampler2x4Neon () Upsampler2xNeon <NC>::Upsampler2xNeon ()
: _filter () : _filter ()
{ {
for (int i = 0; i < NBR_COEFS + 2; ++i) for (int i = 0; i < NBR_STAGES + 1; ++i)
{ {
_filter [i]._coef4 = vdupq_n_f32 (0); _filter [i]._coef4 = vdupq_n_f32 (0);
} }
if ((NBR_COEFS & 1) != 0)
{
const int pos = (NBR_COEFS ^ 1) & (STAGE_WIDTH - 1);
_filter [NBR_STAGES]._coef [pos] = 1;
}
clear_buffers (); clear_buffers ();
} }
@ -73,13 +80,15 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
void Upsampler2x4Neon <NC>::set_coefs (const double coef_arr [NBR_COEFS]) void Upsampler2xNeon <NC>::set_coefs (const double coef_arr [NBR_COEFS])
{ {
assert (coef_arr != 0); assert (coef_arr != 0);
for (int i = 0; i < NBR_COEFS; ++i) for (int i = 0; i < NBR_COEFS; ++i)
{ {
_filter [i + 2]._coef4 = vdupq_n_f32 (float (coef_arr [i])); const int stage = (i / STAGE_WIDTH) + 1;
const int pos = (i ^ 1) & (STAGE_WIDTH - 1);
_filter [stage]._coef [pos] = float (coef_arr [i]);
} }
} }
@ -89,29 +98,29 @@ void Upsampler2x4Neon <NC>::set_coefs (const double coef_arr [NBR_COEFS])
============================================================================== ==============================================================================
Name: process_sample Name: process_sample
Description: Description:
Upsamples (x2) the input vector, generating two output vectors. Upsamples (x2) the input sample, generating two output samples.
Input parameters: Input parameters:
- input: The input vector. - input: The input sample.
Output parameters: Output parameters:
- out_0: First output vector. - out_0: First output sample.
- out_1: Second output vector. - out_1: Second output sample.
Throws: Nothing Throws: Nothing
============================================================================== ==============================================================================
*/ */
template <int NC> template <int NC>
void Upsampler2x4Neon <NC>::process_sample (float32x4_t &out_0, float32x4_t &out_1, float32x4_t input) void Upsampler2xNeon <NC>::process_sample (float &out_0, float &out_1, float input)
{ {
float32x4_t even = input; const float32x2_t spl_in = vdup_n_f32 (input);
float32x4_t odd = input; const float32x2_t spl_mid = vget_low_f32 (_filter [NBR_STAGES]._mem4);
StageProc4Neon <NBR_COEFS>::process_sample_pos ( float32x4_t y = vcombine_f32 (spl_in, spl_mid);
NBR_COEFS, float32x4_t mem = _filter [0]._mem4;
even,
odd, StageProcNeon <NBR_STAGES>::process_sample_pos (&_filter [0], y, mem);
&_filter [0] _filter [NBR_STAGES]._mem4 = y;
);
out_0 = even; out_0 = vgetq_lane_f32 (y, 3);
out_1 = odd; out_1 = vgetq_lane_f32 (y, 2);
} }
@ -120,44 +129,29 @@ void Upsampler2x4Neon <NC>::process_sample (float32x4_t &out_0, float32x4_t &out
============================================================================== ==============================================================================
Name: process_block Name: process_block
Description: Description:
Upsamples (x2) the input vector block. Upsamples (x2) the input sample block.
Input and output blocks may overlap, see assert() for details. Input and output blocks may overlap, see assert() for details.
Input parameters: Input parameters:
- in_ptr: Input array, containing nbr_spl vector. - in_ptr: Input array, containing nbr_spl samples.
No alignment constraint. - nbr_spl: Number of input samples to process, > 0
- nbr_spl: Number of input vectors to process, > 0
Output parameters: Output parameters:
- out_0_ptr: Output vector array, capacity: nbr_spl * 2 vectors. - out_0_ptr: Output sample array, capacity: nbr_spl * 2 samples.
No alignment constraint.
Throws: Nothing Throws: Nothing
============================================================================== ==============================================================================
*/ */
template <int NC> template <int NC>
void Upsampler2x4Neon <NC>::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) void Upsampler2xNeon <NC>::process_block (float out_ptr [], const float in_ptr [], long nbr_spl)
{ {
assert (out_ptr != 0); assert (out_ptr != 0);
assert (in_ptr != 0); assert (in_ptr != 0);
assert (out_ptr >= in_ptr + nbr_spl * 4 || in_ptr >= out_ptr + nbr_spl * 4); assert (out_ptr >= in_ptr + nbr_spl || in_ptr >= out_ptr + nbr_spl);
assert (nbr_spl > 0); assert (nbr_spl > 0);
long pos = 0; long pos = 0;
do do
{ {
const float32x4_t src = vreinterpretq_f32_u8 ( process_sample (out_ptr [pos * 2], out_ptr [pos * 2 + 1], in_ptr [pos]);
vld1q_u8 (reinterpret_cast <const uint8_t *> (in_ptr + pos * 4))
);
float32x4_t dst_0;
float32x4_t dst_1;
process_sample (dst_0, dst_1, src);
vst1q_u8 (
reinterpret_cast <uint8_t *> (out_ptr + pos * 8 ),
vreinterpretq_u8_f32 (dst_0)
);
vst1q_u8 (
reinterpret_cast <uint8_t *> (out_ptr + pos * 8 + 4),
vreinterpretq_u8_f32 (dst_1)
);
++ pos; ++ pos;
} }
while (pos < nbr_spl); while (pos < nbr_spl);
@ -176,9 +170,9 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
void Upsampler2x4Neon <NC>::clear_buffers () void Upsampler2xNeon <NC>::clear_buffers ()
{ {
for (int i = 0; i < NBR_COEFS + 2; ++i) for (int i = 0; i < NBR_STAGES + 1; ++i)
{ {
_filter [i]._mem4 = vdupq_n_f32 (0); _filter [i]._mem4 = vdupq_n_f32 (0);
} }
@ -198,7 +192,7 @@ void Upsampler2x4Neon <NC>::clear_buffers ()
#endif // hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED #endif // hiir_Upsampler2xNeon_CODEHEADER_INCLUDED

119
src/external/hiir/Upsampler2xSse.h vendored Normal file
View file

@ -0,0 +1,119 @@
/*****************************************************************************
Upsampler2xSse.h
Author: Laurent de Soras, 2005
Upsamples by a factor 2 the input signal, using SSE instruction set.
This object must be aligned on a 16-byte boundary!
If the number of coefficients is 2 or 3 modulo 4, the output is delayed from
1 sample, compared to the theoretical formula (or FPU implementation).
Template parameters:
- NC: number of coefficients, > 0
--- Legal stuff ---
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*Tab=3***********************************************************************/
#if ! defined (hiir_Upsampler2xSse_HEADER_INCLUDED)
#define hiir_Upsampler2xSse_HEADER_INCLUDED
#if defined (_MSC_VER)
#pragma once
#pragma warning (4 : 4250) // "Inherits via dominance."
#endif
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageDataSse.h"
#include <xmmintrin.h>
#include <array>
namespace hiir
{
template <int NC>
class Upsampler2xSse
{
static_assert ((NC > 0), "Number of coefficient must be positive.");
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public:
enum { NBR_COEFS = NC };
Upsampler2xSse ();
Upsampler2xSse (const Upsampler2xSse &other) = default;
Upsampler2xSse &
operator = (const Upsampler2xSse &other) = default;
void set_coefs (const double coef_arr [NBR_COEFS]);
inline void process_sample (float &out_0, float &out_1, float input);
void process_block (float out_ptr [], const float in_ptr [], long nbr_spl);
void clear_buffers ();
/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
protected:
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
enum { STAGE_WIDTH = 4 };
enum { NBR_STAGES = (NBR_COEFS + STAGE_WIDTH - 1) / STAGE_WIDTH };
typedef std::array <StageDataSse, NBR_STAGES + 1> Filter; // Stage 0 contains only input memory
Filter _filter; // Should be the first member (thus easier to align)
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
bool operator == (const Upsampler2xSse <NC> &other) const = delete;
bool operator != (const Upsampler2xSse <NC> &other) const = delete;
}; // class Upsampler2xSse
} // namespace hiir
#include "hiir/Upsampler2xSse.hpp"
#endif // hiir_Upsampler2xSse_HEADER_INCLUDED
/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

View file

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Upsampler2x4Sse.hpp Upsampler2xSse.hpp
Author: Laurent de Soras, 2015 Author: Laurent de Soras, 2005
--- Legal stuff --- --- Legal stuff ---
@ -15,14 +15,21 @@ http://sam.zoy.org/wtfpl/COPYING for more details.
#if ! defined (hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED) #if defined (hiir_Upsampler2xSse_CURRENT_CODEHEADER)
#define hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED #error Recursive inclusion of Upsampler2xSse code header.
#endif
#define hiir_Upsampler2xSse_CURRENT_CODEHEADER
#if ! defined (hiir_Upsampler2xSse_CODEHEADER_INCLUDED)
#define hiir_Upsampler2xSse_CODEHEADER_INCLUDED
/*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#include "hiir/StageProc4Sse.h" #include "hiir/StageProcSse.h"
#include <xmmintrin.h>
#include <cassert> #include <cassert>
@ -45,12 +52,20 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
Upsampler2x4Sse <NC>::Upsampler2x4Sse () Upsampler2xSse <NC>::Upsampler2xSse ()
: _filter () : _filter ()
{ {
for (int i = 0; i < NBR_COEFS + 2; ++i) for (int i = 0; i < NBR_STAGES + 1; ++i)
{ {
_mm_store_ps (_filter [i]._coef, _mm_setzero_ps ()); _filter [i]._coef [0] = 0;
_filter [i]._coef [1] = 0;
_filter [i]._coef [2] = 0;
_filter [i]._coef [3] = 0;
}
if ((NBR_COEFS & 1) != 0)
{
const int pos = (NBR_COEFS ^ 1) & (STAGE_WIDTH - 1);
_filter [NBR_STAGES]._coef [pos] = 1;
} }
clear_buffers (); clear_buffers ();
@ -73,13 +88,15 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
void Upsampler2x4Sse <NC>::set_coefs (const double coef_arr [NBR_COEFS]) void Upsampler2xSse <NC>::set_coefs (const double coef_arr [NBR_COEFS])
{ {
assert (coef_arr != 0); assert (coef_arr != 0);
for (int i = 0; i < NBR_COEFS; ++i) for (int i = 0; i < NBR_COEFS; ++i)
{ {
_mm_store_ps (_filter [i + 2]._coef, _mm_set1_ps (float (coef_arr [i]))); const int stage = (i / STAGE_WIDTH) + 1;
const int pos = (i ^ 1) & (STAGE_WIDTH - 1);
_filter [stage]._coef [pos] = float (coef_arr [i]);
} }
} }
@ -89,29 +106,34 @@ void Upsampler2x4Sse <NC>::set_coefs (const double coef_arr [NBR_COEFS])
============================================================================== ==============================================================================
Name: process_sample Name: process_sample
Description: Description:
Upsamples (x2) the input vector, generating two output vectors. Upsamples (x2) the input sample, generating two output samples.
Input parameters: Input parameters:
- input: The input vector. - input: The input sample.
Output parameters: Output parameters:
- out_0: First output vector. - out_0: First output sample.
- out_1: Second output vector. - out_1: Second output sample.
Throws: Nothing Throws: Nothing
============================================================================== ==============================================================================
*/ */
template <int NC> template <int NC>
void Upsampler2x4Sse <NC>::process_sample (__m128 &out_0, __m128 &out_1, __m128 input) void Upsampler2xSse <NC>::process_sample (float &out_0, float &out_1, float input)
{ {
__m128 even = input; const __m128 spl_in = _mm_set_ss (input);
__m128 odd = input; const __m128 spl_mid = _mm_load_ps (_filter [NBR_STAGES]._mem);
StageProc4Sse <NBR_COEFS>::process_sample_pos ( __m128 y = _mm_shuffle_ps (spl_in, spl_mid, 0x40);
NBR_COEFS,
even, __m128 mem = _mm_load_ps (_filter [0]._mem);
odd,
&_filter [0] StageProcSse <NBR_STAGES>::process_sample_pos (&_filter [0], y, mem);
);
out_0 = even; _mm_store_ps (_filter [NBR_STAGES]._mem, y);
out_1 = odd;
// The latest shufps/movss instruction pairs can be freely inverted
y = _mm_shuffle_ps (y, y, 0xE3);
_mm_store_ss (&out_0, y);
y = _mm_shuffle_ps (y, y, 0xE2);
_mm_store_ss (&out_1, y);
} }
@ -120,36 +142,29 @@ void Upsampler2x4Sse <NC>::process_sample (__m128 &out_0, __m128 &out_1, __m128
============================================================================== ==============================================================================
Name: process_block Name: process_block
Description: Description:
Upsamples (x2) the input vector block. Upsamples (x2) the input sample block.
Input and output blocks may overlap, see assert() for details. Input and output blocks may overlap, see assert() for details.
Input parameters: Input parameters:
- in_ptr: Input array, containing nbr_spl vector. - in_ptr: Input array, containing nbr_spl samples.
No alignment constraint. - nbr_spl: Number of input samples to process, > 0
- nbr_spl: Number of input vectors to process, > 0
Output parameters: Output parameters:
- out_0_ptr: Output vector array, capacity: nbr_spl * 2 vectors. - out_0_ptr: Output sample array, capacity: nbr_spl * 2 samples.
No alignment constraint.
Throws: Nothing Throws: Nothing
============================================================================== ==============================================================================
*/ */
template <int NC> template <int NC>
void Upsampler2x4Sse <NC>::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) void Upsampler2xSse <NC>::process_block (float out_ptr [], const float in_ptr [], long nbr_spl)
{ {
assert (out_ptr != 0); assert (out_ptr != 0);
assert (in_ptr != 0); assert (in_ptr != 0);
assert (out_ptr >= in_ptr + nbr_spl * 4 || in_ptr >= out_ptr + nbr_spl * 4); assert (out_ptr >= in_ptr + nbr_spl || in_ptr >= out_ptr + nbr_spl);
assert (nbr_spl > 0); assert (nbr_spl > 0);
long pos = 0; long pos = 0;
do do
{ {
__m128 dst_0; process_sample (out_ptr [pos * 2], out_ptr [pos * 2 + 1], in_ptr [pos]);
__m128 dst_1;
const __m128 src = _mm_loadu_ps (in_ptr + pos * 4);
process_sample (dst_0, dst_1, src);
_mm_storeu_ps (out_ptr + pos * 8 , dst_0);
_mm_storeu_ps (out_ptr + pos * 8 + 4, dst_1);
++ pos; ++ pos;
} }
while (pos < nbr_spl); while (pos < nbr_spl);
@ -168,11 +183,14 @@ Throws: Nothing
*/ */
template <int NC> template <int NC>
void Upsampler2x4Sse <NC>::clear_buffers () void Upsampler2xSse <NC>::clear_buffers ()
{ {
for (int i = 0; i < NBR_COEFS + 2; ++i) for (int i = 0; i < NBR_STAGES + 1; ++i)
{ {
_mm_store_ps (_filter [i]._mem, _mm_setzero_ps ()); _filter [i]._mem [0] = 0;
_filter [i]._mem [1] = 0;
_filter [i]._mem [2] = 0;
_filter [i]._mem [3] = 0;
} }
} }
@ -186,11 +204,13 @@ void Upsampler2x4Sse <NC>::clear_buffers ()
} // namespace hiir } // namespace hiir
#endif // hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED #endif // hiir_Upsampler2xSse_CODEHEADER_INCLUDED
#undef hiir_Upsampler2xSse_CURRENT_CODEHEADER

View file

@ -61,7 +61,7 @@ constexpr std::array<double, 3> coeffsStage8x {
}; };
template<bool SIMD=SIMDConfig::upsampling> template<bool SIMD=SIMDConfig::upsampling>
inline void upsample2xStage(absl::Span<const float> input, absl::Span<float> output) void upsample2xStage(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2xFpu<coeffsStage2x.size()> upsampler; hiir::Upsampler2xFpu<coeffsStage2x.size()> upsampler;
@ -71,7 +71,7 @@ inline void upsample2xStage(absl::Span<const float> input, absl::Span<float> out
template<bool SIMD=SIMDConfig::upsampling> template<bool SIMD=SIMDConfig::upsampling>
inline void upsample4xStage(absl::Span<const float> input, absl::Span<float> output) void upsample4xStage(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2xFpu<coeffsStage4x.size()> upsampler; hiir::Upsampler2xFpu<coeffsStage4x.size()> upsampler;
@ -80,7 +80,7 @@ inline void upsample4xStage(absl::Span<const float> input, absl::Span<float> out
} }
template<bool SIMD=SIMDConfig::upsampling> template<bool SIMD=SIMDConfig::upsampling>
inline void upsample8xStage(absl::Span<const float> input, absl::Span<float> output) void upsample8xStage(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2xFpu<coeffsStage8x.size()> upsampler; hiir::Upsampler2xFpu<coeffsStage8x.size()> upsampler;
@ -89,11 +89,11 @@ inline void upsample8xStage(absl::Span<const float> input, absl::Span<float> out
} }
template<> template<>
inline void upsample2xStage<true>(absl::Span<const float> input, absl::Span<float> output); void upsample2xStage<true>(absl::Span<const float> input, absl::Span<float> output);
template<> template<>
inline void upsample4xStage<true>(absl::Span<const float> input, absl::Span<float> output); void upsample4xStage<true>(absl::Span<const float> input, absl::Span<float> output);
template<> template<>
inline void upsample8xStage<true>(absl::Span<const float> input, absl::Span<float> output); void upsample8xStage<true>(absl::Span<const float> input, absl::Span<float> output);
template <class T, bool SIMD=SIMDConfig::upsampling> template <class T, bool SIMD=SIMDConfig::upsampling>
std::unique_ptr<sfz::AudioBuffer<T>> upsample2x(const sfz::AudioBuffer<T>& buffer) std::unique_ptr<sfz::AudioBuffer<T>> upsample2x(const sfz::AudioBuffer<T>& buffer)

View file

@ -22,29 +22,31 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Oversampler.h" #include "Oversampler.h"
#include "hiir/Upsampler2x4Sse.h" #include "hiir/Upsampler2xSse.h"
template<> template<>
inline void sfz::upsample2xStage<true>(absl::Span<const float> input, absl::Span<float> output) void sfz::upsample2xStage<true>(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2x4Sse<sfz::coeffsStage2x.size()> upsampler; hiir::Upsampler2xSse<sfz::coeffsStage2x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage2x.data()); upsampler.set_coefs(sfz::coeffsStage2x.data());
upsampler.process_block(output.data(), input.data(), input.size()); upsampler.process_block(output.data(), input.data(), input.size());
} }
template<> template<>
inline void sfz::upsample4xStage<true>(absl::Span<const float> input, absl::Span<float> output) void sfz::upsample4xStage<true>(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2x4Sse<sfz::coeffsStage4x.size()> upsampler; hiir::Upsampler2xSse<sfz::coeffsStage4x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage4x.data()); upsampler.set_coefs(sfz::coeffsStage4x.data());
upsampler.process_block(output.data(), input.data(), input.size()); upsampler.process_block(output.data(), input.data(), input.size());
} }
template<> template<>
inline void sfz::upsample8xStage<true>(absl::Span<const float> input, absl::Span<float> output) void sfz::upsample8xStage<true>(absl::Span<const float> input, absl::Span<float> output)
{ {
ASSERT(output.size() >= 2 * input.size()); ASSERT(output.size() >= 2 * input.size());
hiir::Upsampler2x4Sse<sfz::coeffsStage8x.size()> upsampler; hiir::Upsampler2xSse<sfz::coeffsStage8x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage8x.data()); upsampler.set_coefs(sfz::coeffsStage8x.data());
upsampler.process_block(output.data(), input.data(), input.size()); upsampler.process_block(output.data(), input.data(), input.size());
} }