diff --git a/src/external/hiir/StageProc4Neon.hpp b/src/external/hiir/StageProc4Neon.hpp deleted file mode 100644 index 72ce50ea..00000000 --- a/src/external/hiir/StageProc4Neon.hpp +++ /dev/null @@ -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 -void StageProc4Neon ::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 ::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 -void StageProc4Neon ::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 ::process_sample_neg ( - nbr_coefs, - spl_0, - spl_1, - stage_arr - ); -} - - - -/*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ - - - -/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ - - - -} // namespace hiir - - - -#endif // hiir_StageProc4Neon_CODEHEADER_INCLUDED - - - -/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/StageProc4Sse.hpp b/src/external/hiir/StageProc4Sse.hpp deleted file mode 100644 index 1419e826..00000000 --- a/src/external/hiir/StageProc4Sse.hpp +++ /dev/null @@ -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 -void StageProc4Sse ::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 ::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 -void StageProc4Sse ::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 ::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 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/StageProc4Neon.h b/src/external/hiir/StageProcNeon.h similarity index 50% rename from src/external/hiir/StageProc4Neon.h rename to src/external/hiir/StageProcNeon.h index 534cb9c5..f2e3bce1 100644 --- a/src/external/hiir/StageProc4Neon.h +++ b/src/external/hiir/StageProcNeon.h @@ -1,10 +1,10 @@ /***************************************************************************** - StageProc4Neon.h + StageProcNeon.h Author: Laurent de Soras, 2016 Template parameters: - - REMAINING: Number of remaining coefficients to process, >= 0 + - CUR: index of the coefficient coefficient to process, >= 0 --- Legal stuff --- @@ -19,8 +19,8 @@ http://sam.zoy.org/wtfpl/COPYING for more details. #pragma once -#if ! defined (hiir_StageProc4Neon_HEADER_INCLUDED) -#define hiir_StageProc4Neon_HEADER_INCLUDED +#if ! defined (hiir_StageProcNeon_HEADER_INCLUDED) +#define hiir_StageProcNeon_HEADER_INCLUDED #if defined (_MSC_VER) #pragma warning (4 : 4250) @@ -41,19 +41,20 @@ namespace hiir class StageDataNeon; -template -class StageProc4Neon +template +class StageProcNeon { - static_assert (REMAINING >= 0, "REMAINING must be >= 0."); + + static_assert ((CUR >= 0), "CUR must be >= 0"); /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ public: 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 - 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: + enum { PREV = CUR - 1 }; + /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ private: - StageProc4Neon () = delete; - StageProc4Neon (const StageProc4Neon &other) = delete; - ~StageProc4Neon () = delete; - StageProc4Neon & - operator = (const StageProc4Neon &other) = delete; - bool operator == (const StageProc4Neon &other) const = delete; - bool operator != (const StageProc4Neon &other) const = delete; + StageProcNeon () = delete; + StageProcNeon (const StageProcNeon &other) = delete; + ~StageProcNeon () = delete; + StageProcNeon & + operator = (const StageProcNeon &other) = delete; + bool operator == (const StageProcNeon &other) const = delete; + bool operator != (const StageProcNeon &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 diff --git a/src/external/hiir/StageProcNeon.hpp b/src/external/hiir/StageProcNeon.hpp new file mode 100644 index 00000000..c979ae20 --- /dev/null +++ b/src/external/hiir/StageProcNeon.hpp @@ -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 +void StageProcNeon ::process_sample_pos (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem) +{ + StageProcNeon ::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 +void StageProcNeon ::process_sample_neg (StageDataNeon *stage_ptr, float32x4_t &y, float32x4_t &mem) +{ + StageProcNeon ::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 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/StageProc4Sse.h b/src/external/hiir/StageProcSse.h similarity index 54% rename from src/external/hiir/StageProc4Sse.h rename to src/external/hiir/StageProcSse.h index 4b697aa7..ab27fef9 100644 --- a/src/external/hiir/StageProc4Sse.h +++ b/src/external/hiir/StageProcSse.h @@ -1,10 +1,10 @@ /***************************************************************************** - StageProc4Sse.h - Author: Laurent de Soras, 2015 + StageProcSse.h + Author: Laurent de Soras, 2005 Template parameters: - - REMAINING: Number of remaining coefficients to process, >= 0 + - CUR: index of the coefficient to process, >= 0 --- Legal stuff --- @@ -18,8 +18,8 @@ http://sam.zoy.org/wtfpl/COPYING for more details. -#if ! defined (hiir_StageProc4Sse_HEADER_INCLUDED) -#define hiir_StageProc4Sse_HEADER_INCLUDED +#if ! defined (hiir_StageProcSse_HEADER_INCLUDED) +#define hiir_StageProcSse_HEADER_INCLUDED #if defined (_MSC_VER) #pragma once @@ -43,20 +43,20 @@ namespace hiir class StageDataSse; -template -class StageProc4Sse +template +class StageProcSse { - static_assert ((REMAINING >= 0), "REMAINING must be >= 0"); + static_assert ((CUR >= 0), "CUR must be >= 0"); /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ public: 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 - 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: + enum { PREV = CUR - 1 }; + /*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ private: - StageProc4Sse (); - StageProc4Sse (const StageProc4Sse &other); - StageProc4Sse & - operator = (const StageProc4Sse &other); - bool operator == (const StageProc4Sse &other); - bool operator != (const StageProc4Sse &other); + StageProcSse (); + StageProcSse (const StageProcSse &other); + StageProcSse & + operator = (const StageProcSse &other); + bool operator == (const StageProcSse &other); + bool operator != (const StageProcSse &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 diff --git a/src/external/hiir/StageProcSse.hpp b/src/external/hiir/StageProcSse.hpp new file mode 100644 index 00000000..97942e17 --- /dev/null +++ b/src/external/hiir/StageProcSse.hpp @@ -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 +void StageProcSse ::process_sample_pos (StageDataSse *stage_ptr, __m128 &y, __m128 &mem) +{ + StageProcSse ::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 +void StageProcSse ::process_sample_neg (StageDataSse *stage_ptr, __m128 &y, __m128 &mem) +{ + StageProcSse ::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 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/Upsampler2x4Neon.h b/src/external/hiir/Upsampler2x4Neon.h deleted file mode 100644 index aeb56751..00000000 --- a/src/external/hiir/Upsampler2x4Neon.h +++ /dev/null @@ -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 - -#include - - - -namespace hiir -{ - - - -template -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 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 &other) const = delete; - bool operator != (const Upsampler2x4Neon &other) const = delete; - -}; // class Upsampler2x4Neon - - - -} // namespace hiir - - - -#include "hiir/Upsampler2x4Neon.hpp" - - - -#endif // hiir_Upsampler2x4Neon_HEADER_INCLUDED - - - -/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/Upsampler2x4Sse.h b/src/external/hiir/Upsampler2x4Sse.h deleted file mode 100644 index 629abc07..00000000 --- a/src/external/hiir/Upsampler2x4Sse.h +++ /dev/null @@ -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 - -#include - - - -namespace hiir -{ - - - -template -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 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 &other) const; - bool operator != (const Upsampler2x4Sse &other) const; - -}; // class Upsampler2x4Sse - - - -} // namespace hiir - - - -#include "hiir/Upsampler2x4Sse.hpp" - - - -#endif // hiir_Upsampler2x4Sse_HEADER_INCLUDED - - - -/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/Upsampler2xNeon.h b/src/external/hiir/Upsampler2xNeon.h new file mode 100644 index 00000000..22abacba --- /dev/null +++ b/src/external/hiir/Upsampler2xNeon.h @@ -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 + + + +namespace hiir +{ + + + +template +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 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 &other) const = delete; + bool operator != (const Upsampler2xNeon &other) const = delete; + +}; // class Upsampler2xNeon + + + +} // namespace hiir + + + +#include "hiir/Upsampler2xNeon.hpp" + + + +#endif // hiir_Upsampler2xNeon_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/Upsampler2x4Neon.hpp b/src/external/hiir/Upsampler2xNeon.hpp similarity index 59% rename from src/external/hiir/Upsampler2x4Neon.hpp rename to src/external/hiir/Upsampler2xNeon.hpp index 6304ed15..8ff9397e 100644 --- a/src/external/hiir/Upsampler2x4Neon.hpp +++ b/src/external/hiir/Upsampler2xNeon.hpp @@ -1,6 +1,6 @@ /***************************************************************************** - Upsampler2x4Neon.hpp + Upsampler2xNeon.hpp Author: Laurent de Soras, 2016 --- Legal stuff --- @@ -15,14 +15,16 @@ http://sam.zoy.org/wtfpl/COPYING for more details. -#if ! defined (hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED) -#define hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED +#if ! defined (hiir_Upsampler2xNeon_CODEHEADER_INCLUDED) +#define hiir_Upsampler2xNeon_CODEHEADER_INCLUDED /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ -#include "hiir/StageProc4Neon.h" +#include "hiir/StageProcNeon.h" + +#include #include @@ -45,13 +47,18 @@ Throws: Nothing */ template -Upsampler2x4Neon ::Upsampler2x4Neon () +Upsampler2xNeon ::Upsampler2xNeon () : _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); } + if ((NBR_COEFS & 1) != 0) + { + const int pos = (NBR_COEFS ^ 1) & (STAGE_WIDTH - 1); + _filter [NBR_STAGES]._coef [pos] = 1; + } clear_buffers (); } @@ -73,13 +80,15 @@ Throws: Nothing */ template -void Upsampler2x4Neon ::set_coefs (const double coef_arr [NBR_COEFS]) +void Upsampler2xNeon ::set_coefs (const double coef_arr [NBR_COEFS]) { assert (coef_arr != 0); 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 ::set_coefs (const double coef_arr [NBR_COEFS]) ============================================================================== Name: process_sample Description: - Upsamples (x2) the input vector, generating two output vectors. + Upsamples (x2) the input sample, generating two output samples. Input parameters: - - input: The input vector. + - input: The input sample. Output parameters: - - out_0: First output vector. - - out_1: Second output vector. + - out_0: First output sample. + - out_1: Second output sample. Throws: Nothing ============================================================================== */ template -void Upsampler2x4Neon ::process_sample (float32x4_t &out_0, float32x4_t &out_1, float32x4_t input) +void Upsampler2xNeon ::process_sample (float &out_0, float &out_1, float input) { - float32x4_t even = input; - float32x4_t odd = input; - StageProc4Neon ::process_sample_pos ( - NBR_COEFS, - even, - odd, - &_filter [0] - ); - out_0 = even; - out_1 = odd; + const float32x2_t spl_in = vdup_n_f32 (input); + const float32x2_t spl_mid = vget_low_f32 (_filter [NBR_STAGES]._mem4); + float32x4_t y = vcombine_f32 (spl_in, spl_mid); + float32x4_t mem = _filter [0]._mem4; + + StageProcNeon ::process_sample_pos (&_filter [0], y, mem); + _filter [NBR_STAGES]._mem4 = y; + + out_0 = vgetq_lane_f32 (y, 3); + out_1 = vgetq_lane_f32 (y, 2); } @@ -120,44 +129,29 @@ void Upsampler2x4Neon ::process_sample (float32x4_t &out_0, float32x4_t &out ============================================================================== Name: process_block Description: - Upsamples (x2) the input vector block. + Upsamples (x2) the input sample block. Input and output blocks may overlap, see assert() for details. Input parameters: - - in_ptr: Input array, containing nbr_spl vector. - No alignment constraint. - - nbr_spl: Number of input vectors to process, > 0 + - in_ptr: Input array, containing nbr_spl samples. + - nbr_spl: Number of input samples to process, > 0 Output parameters: - - out_0_ptr: Output vector array, capacity: nbr_spl * 2 vectors. - No alignment constraint. + - out_0_ptr: Output sample array, capacity: nbr_spl * 2 samples. Throws: Nothing ============================================================================== */ template -void Upsampler2x4Neon ::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) +void Upsampler2xNeon ::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) { assert (out_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); long pos = 0; do { - const float32x4_t src = vreinterpretq_f32_u8 ( - vld1q_u8 (reinterpret_cast (in_ptr + pos * 4)) - ); - float32x4_t dst_0; - float32x4_t dst_1; - process_sample (dst_0, dst_1, src); - vst1q_u8 ( - reinterpret_cast (out_ptr + pos * 8 ), - vreinterpretq_u8_f32 (dst_0) - ); - vst1q_u8 ( - reinterpret_cast (out_ptr + pos * 8 + 4), - vreinterpretq_u8_f32 (dst_1) - ); + process_sample (out_ptr [pos * 2], out_ptr [pos * 2 + 1], in_ptr [pos]); ++ pos; } while (pos < nbr_spl); @@ -176,9 +170,9 @@ Throws: Nothing */ template -void Upsampler2x4Neon ::clear_buffers () +void Upsampler2xNeon ::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); } @@ -198,7 +192,7 @@ void Upsampler2x4Neon ::clear_buffers () -#endif // hiir_Upsampler2x4Neon_CODEHEADER_INCLUDED +#endif // hiir_Upsampler2xNeon_CODEHEADER_INCLUDED diff --git a/src/external/hiir/Upsampler2xSse.h b/src/external/hiir/Upsampler2xSse.h new file mode 100644 index 00000000..6366de62 --- /dev/null +++ b/src/external/hiir/Upsampler2xSse.h @@ -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 + +#include + + + +namespace hiir +{ + + + +template +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 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 &other) const = delete; + bool operator != (const Upsampler2xSse &other) const = delete; + +}; // class Upsampler2xSse + + + +} // namespace hiir + + + +#include "hiir/Upsampler2xSse.hpp" + + + +#endif // hiir_Upsampler2xSse_HEADER_INCLUDED + + + +/*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/ diff --git a/src/external/hiir/Upsampler2x4Sse.hpp b/src/external/hiir/Upsampler2xSse.hpp similarity index 51% rename from src/external/hiir/Upsampler2x4Sse.hpp rename to src/external/hiir/Upsampler2xSse.hpp index 9228894a..5a720a8d 100644 --- a/src/external/hiir/Upsampler2x4Sse.hpp +++ b/src/external/hiir/Upsampler2xSse.hpp @@ -1,7 +1,7 @@ /***************************************************************************** - Upsampler2x4Sse.hpp - Author: Laurent de Soras, 2015 + Upsampler2xSse.hpp + Author: Laurent de Soras, 2005 --- Legal stuff --- @@ -15,14 +15,21 @@ http://sam.zoy.org/wtfpl/COPYING for more details. -#if ! defined (hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED) -#define hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED +#if defined (hiir_Upsampler2xSse_CURRENT_CODEHEADER) + #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 "hiir/StageProc4Sse.h" +#include "hiir/StageProcSse.h" + +#include #include @@ -45,12 +52,20 @@ Throws: Nothing */ template -Upsampler2x4Sse ::Upsampler2x4Sse () +Upsampler2xSse ::Upsampler2xSse () : _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 (); @@ -73,13 +88,15 @@ Throws: Nothing */ template -void Upsampler2x4Sse ::set_coefs (const double coef_arr [NBR_COEFS]) +void Upsampler2xSse ::set_coefs (const double coef_arr [NBR_COEFS]) { assert (coef_arr != 0); 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 ::set_coefs (const double coef_arr [NBR_COEFS]) ============================================================================== Name: process_sample Description: - Upsamples (x2) the input vector, generating two output vectors. + Upsamples (x2) the input sample, generating two output samples. Input parameters: - - input: The input vector. + - input: The input sample. Output parameters: - - out_0: First output vector. - - out_1: Second output vector. + - out_0: First output sample. + - out_1: Second output sample. Throws: Nothing ============================================================================== */ template -void Upsampler2x4Sse ::process_sample (__m128 &out_0, __m128 &out_1, __m128 input) +void Upsampler2xSse ::process_sample (float &out_0, float &out_1, float input) { - __m128 even = input; - __m128 odd = input; - StageProc4Sse ::process_sample_pos ( - NBR_COEFS, - even, - odd, - &_filter [0] - ); - out_0 = even; - out_1 = odd; + const __m128 spl_in = _mm_set_ss (input); + const __m128 spl_mid = _mm_load_ps (_filter [NBR_STAGES]._mem); + __m128 y = _mm_shuffle_ps (spl_in, spl_mid, 0x40); + + __m128 mem = _mm_load_ps (_filter [0]._mem); + + StageProcSse ::process_sample_pos (&_filter [0], y, mem); + + _mm_store_ps (_filter [NBR_STAGES]._mem, y); + + // 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 ::process_sample (__m128 &out_0, __m128 &out_1, __m128 ============================================================================== Name: process_block Description: - Upsamples (x2) the input vector block. + Upsamples (x2) the input sample block. Input and output blocks may overlap, see assert() for details. Input parameters: - - in_ptr: Input array, containing nbr_spl vector. - No alignment constraint. - - nbr_spl: Number of input vectors to process, > 0 + - in_ptr: Input array, containing nbr_spl samples. + - nbr_spl: Number of input samples to process, > 0 Output parameters: - - out_0_ptr: Output vector array, capacity: nbr_spl * 2 vectors. - No alignment constraint. + - out_0_ptr: Output sample array, capacity: nbr_spl * 2 samples. Throws: Nothing ============================================================================== */ template -void Upsampler2x4Sse ::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) +void Upsampler2xSse ::process_block (float out_ptr [], const float in_ptr [], long nbr_spl) { assert (out_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); long pos = 0; do { - __m128 dst_0; - __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); + process_sample (out_ptr [pos * 2], out_ptr [pos * 2 + 1], in_ptr [pos]); ++ pos; } while (pos < nbr_spl); @@ -168,11 +183,14 @@ Throws: Nothing */ template -void Upsampler2x4Sse ::clear_buffers () +void Upsampler2xSse ::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 ::clear_buffers () -} // namespace hiir +} // namespace hiir -#endif // hiir_Upsampler2x4Sse_CODEHEADER_INCLUDED +#endif // hiir_Upsampler2xSse_CODEHEADER_INCLUDED + +#undef hiir_Upsampler2xSse_CURRENT_CODEHEADER diff --git a/src/sfizz/Oversampler.h b/src/sfizz/Oversampler.h index b0fafa1b..66c419aa 100644 --- a/src/sfizz/Oversampler.h +++ b/src/sfizz/Oversampler.h @@ -61,7 +61,7 @@ constexpr std::array coeffsStage8x { }; template -inline void upsample2xStage(absl::Span input, absl::Span output) +void upsample2xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); hiir::Upsampler2xFpu upsampler; @@ -71,7 +71,7 @@ inline void upsample2xStage(absl::Span input, absl::Span out template -inline void upsample4xStage(absl::Span input, absl::Span output) +void upsample4xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); hiir::Upsampler2xFpu upsampler; @@ -80,7 +80,7 @@ inline void upsample4xStage(absl::Span input, absl::Span out } template -inline void upsample8xStage(absl::Span input, absl::Span output) +void upsample8xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); hiir::Upsampler2xFpu upsampler; @@ -89,11 +89,11 @@ inline void upsample8xStage(absl::Span input, absl::Span out } template<> -inline void upsample2xStage(absl::Span input, absl::Span output); +void upsample2xStage(absl::Span input, absl::Span output); template<> -inline void upsample4xStage(absl::Span input, absl::Span output); +void upsample4xStage(absl::Span input, absl::Span output); template<> -inline void upsample8xStage(absl::Span input, absl::Span output); +void upsample8xStage(absl::Span input, absl::Span output); template std::unique_ptr> upsample2x(const sfz::AudioBuffer& buffer) diff --git a/src/sfizz/OversamplerSSE.cpp b/src/sfizz/OversamplerSSE.cpp index f3617a02..6d233943 100644 --- a/src/sfizz/OversamplerSSE.cpp +++ b/src/sfizz/OversamplerSSE.cpp @@ -22,29 +22,31 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Oversampler.h" -#include "hiir/Upsampler2x4Sse.h" +#include "hiir/Upsampler2xSse.h" template<> -inline void sfz::upsample2xStage(absl::Span input, absl::Span output) +void sfz::upsample2xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); - hiir::Upsampler2x4Sse upsampler; + hiir::Upsampler2xSse upsampler; upsampler.set_coefs(sfz::coeffsStage2x.data()); upsampler.process_block(output.data(), input.data(), input.size()); } + template<> -inline void sfz::upsample4xStage(absl::Span input, absl::Span output) +void sfz::upsample4xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); - hiir::Upsampler2x4Sse upsampler; + hiir::Upsampler2xSse upsampler; upsampler.set_coefs(sfz::coeffsStage4x.data()); upsampler.process_block(output.data(), input.data(), input.size()); } + template<> -inline void sfz::upsample8xStage(absl::Span input, absl::Span output) +void sfz::upsample8xStage(absl::Span input, absl::Span output) { ASSERT(output.size() >= 2 * input.size()); - hiir::Upsampler2x4Sse upsampler; + hiir::Upsampler2xSse upsampler; upsampler.set_coefs(sfz::coeffsStage8x.data()); upsampler.process_block(output.data(), input.data(), input.size()); }