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
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 <int REMAINING>
class StageProc4Neon
template <int CUR>
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 <REMAINING> &other) = delete;
~StageProc4Neon () = delete;
StageProc4Neon <REMAINING> &
operator = (const StageProc4Neon <REMAINING> &other) = delete;
bool operator == (const StageProc4Neon <REMAINING> &other) const = delete;
bool operator != (const StageProc4Neon <REMAINING> &other) const = delete;
StageProcNeon () = delete;
StageProcNeon (const StageProcNeon <CUR> &other) = delete;
~StageProcNeon () = delete;
StageProcNeon &
operator = (const StageProcNeon <CUR> &other) = delete;
bool operator == (const StageProcNeon <CUR> &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
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 <int REMAINING>
class StageProc4Sse
template <int CUR>
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 <REMAINING> &other);
StageProc4Sse <REMAINING> &
operator = (const StageProc4Sse <REMAINING> &other);
bool operator == (const StageProc4Sse <REMAINING> &other);
bool operator != (const StageProc4Sse <REMAINING> &other);
StageProcSse ();
StageProcSse (const StageProcSse <CUR> &other);
StageProcSse <CUR> &
operator = (const StageProcSse <CUR> &other);
bool operator == (const StageProcSse <CUR> &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
--- 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 <arm_neon.h>
#include <cassert>
@ -45,13 +47,18 @@ Throws: Nothing
*/
template <int NC>
Upsampler2x4Neon <NC>::Upsampler2x4Neon ()
Upsampler2xNeon <NC>::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 <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);
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
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 <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;
float32x4_t odd = input;
StageProc4Neon <NBR_COEFS>::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 <NBR_STAGES>::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 <NC>::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 <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 (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 <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)
);
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 <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);
}
@ -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
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 <xmmintrin.h>
#include <cassert>
@ -45,12 +52,20 @@ Throws: Nothing
*/
template <int NC>
Upsampler2x4Sse <NC>::Upsampler2x4Sse ()
Upsampler2xSse <NC>::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 <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);
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
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 <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;
__m128 odd = input;
StageProc4Sse <NBR_COEFS>::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 <NBR_STAGES>::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 <NC>::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 <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 (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 <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>
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());
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>
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());
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>
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());
hiir::Upsampler2xFpu<coeffsStage8x.size()> upsampler;
@ -89,11 +89,11 @@ inline void upsample8xStage(absl::Span<const float> input, absl::Span<float> out
}
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<>
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<>
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>
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.
#include "Oversampler.h"
#include "hiir/Upsampler2x4Sse.h"
#include "hiir/Upsampler2xSse.h"
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());
hiir::Upsampler2x4Sse<sfz::coeffsStage2x.size()> upsampler;
hiir::Upsampler2xSse<sfz::coeffsStage2x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage2x.data());
upsampler.process_block(output.data(), input.data(), input.size());
}
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());
hiir::Upsampler2x4Sse<sfz::coeffsStage4x.size()> upsampler;
hiir::Upsampler2xSse<sfz::coeffsStage4x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage4x.data());
upsampler.process_block(output.data(), input.data(), input.size());
}
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());
hiir::Upsampler2x4Sse<sfz::coeffsStage8x.size()> upsampler;
hiir::Upsampler2xSse<sfz::coeffsStage8x.size()> upsampler;
upsampler.set_coefs(sfz::coeffsStage8x.data());
upsampler.process_block(output.data(), input.data(), input.size());
}