CMSIS-DSP: Added f16 version of biquads.

Corrected few doxygen issues.
pull/19/head
Christophe Favergeon 6 years ago
parent 7c55ae80f7
commit f0750e92c2

@ -65,7 +65,10 @@ __STATIC_FORCEINLINE arm_status arm_sqrt_f16(
}
/**
@} end of SQRT group
*/
#endif /*defined(ARM_FLOAT16_SUPPORTED)*/
#ifdef __cplusplus
}

@ -79,6 +79,126 @@ extern "C"
uint32_t blockSize);
/**
* @brief Instance structure for the floating-point Biquad cascade filter.
*/
typedef struct
{
uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
float16_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */
const float16_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */
} arm_biquad_casd_df1_inst_f16;
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
/**
* @brief Instance structure for the modified Biquad coefs required by vectorized code.
*/
typedef struct
{
float16_t coeffs[12][8]; /**< Points to the array of modified coefficients. The array is of length 32. There is one per stage */
} arm_biquad_mod_coef_f16;
#endif
/**
* @brief Processing function for the floating-point Biquad cascade filter.
* @param[in] S points to an instance of the floating-point Biquad cascade structure.
* @param[in] pSrc points to the block of input data.
* @param[out] pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
*/
void arm_biquad_cascade_df1_f16(
const arm_biquad_casd_df1_inst_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize);
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
void arm_biquad_cascade_df1_mve_init_f16(
arm_biquad_casd_df1_inst_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
arm_biquad_mod_coef_f16 * pCoeffsMod,
float16_t * pState);
#endif
void arm_biquad_cascade_df1_init_f16(
arm_biquad_casd_df1_inst_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState);
/**
* @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter.
*/
typedef struct
{
uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
float16_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */
const float16_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */
} arm_biquad_cascade_df2T_instance_f16;
/**
* @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter.
*/
typedef struct
{
uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
float16_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */
const float16_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */
} arm_biquad_cascade_stereo_df2T_instance_f16;
/**
* @brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
* @param[in] S points to an instance of the filter data structure.
* @param[in] pSrc points to the block of input data.
* @param[out] pDst points to the block of output data
* @param[in] blockSize number of samples to process.
*/
void arm_biquad_cascade_df2T_f16(
const arm_biquad_cascade_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the floating-point transposed direct form II Biquad cascade filter. 2 channels
* @param[in] S points to an instance of the filter data structure.
* @param[in] pSrc points to the block of input data.
* @param[out] pDst points to the block of output data
* @param[in] blockSize number of samples to process.
*/
void arm_biquad_cascade_stereo_df2T_f16(
const arm_biquad_cascade_stereo_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter.
* @param[in,out] S points to an instance of the filter data structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] pCoeffs points to the filter coefficients.
* @param[in] pState points to the state buffer.
*/
void arm_biquad_cascade_df2T_init_f16(
arm_biquad_cascade_df2T_instance_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState);
/**
* @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter.
* @param[in,out] S points to an instance of the filter data structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] pCoeffs points to the filter coefficients.
* @param[in] pState points to the state buffer.
*/
void arm_biquad_cascade_stereo_df2T_init_f16(
arm_biquad_cascade_stereo_df2T_instance_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState);
#endif /*defined(ARM_FLOAT16_SUPPORTED)*/
#ifdef __cplusplus
}

@ -126,6 +126,12 @@ target_sources(CMSISDSPFiltering PRIVATE arm_lms_q31.c)
if ((NOT ARMAC5) AND (NOT DISABLEFLOAT16))
target_sources(CMSISDSPFiltering PRIVATE arm_fir_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_fir_init_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_df1_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_df1_init_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_df2T_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_df2T_init_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_stereo_df2T_f16.c)
target_sources(CMSISDSPFiltering PRIVATE arm_biquad_cascade_stereo_df2T_init_f16.c)
endif()
### Includes

@ -26,3 +26,10 @@
#include "arm_fir_f16.c"
#include "arm_fir_init_f16.c"
#include "arm_biquad_cascade_df1_f16.c"
#include "arm_biquad_cascade_df1_init_f16.c"
#include "arm_biquad_cascade_df2T_f16.c"
#include "arm_biquad_cascade_df2T_init_f16.c"
#include "arm_biquad_cascade_stereo_df2T_f16.c"
#include "arm_biquad_cascade_stereo_df2T_init_f16.c"

@ -0,0 +1,488 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_df1_f16.c
* Description: Processing function for the floating-point Biquad cascade DirectFormI(DF1) filter
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF1
@{
*/
/**
@brief Processing function for the floating-point Biquad cascade filter.
@param[in] S points to an instance of the floating-point Biquad cascade structure
@param[in] pSrc points to the block of input data
@param[out] pDst points to the block of output data
@param[in] blockSize number of samples to process
@return none
*/
#if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE)
#include "arm_helium_utils.h"
void arm_biquad_cascade_df1_f16(
const arm_biquad_casd_df1_inst_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
float16_t *pIn = (float16_t *)pSrc; /* source pointer */
float16_t *pOut = pDst; /* destination pointer */
float16_t *pState = S->pState; /* pState pointer */
const float16_t *pCoeffs = S->pCoeffs; /* coefficient pointer */
float16_t Xn1, Xn2, Yn1, Yn2; /* Filter pState variables */
float16_t X0, X1, X2, X3; /* temporary input */
float16_t X4, X5, X6, X7; /* temporary input */
float16_t lastX, lastY; /* X,Y history for tail handling */
f16x8_t coeffs;
f16x8_t accVec; /* accumultor vector */
uint32_t sample, stage = S->numStages; /* loop counters */
do
{
/*
* Reading the pState values
*/
Xn1 = pState[0];
Xn2 = pState[1];
Yn1 = pState[2];
Yn2 = pState[3];
sample = blockSize >> 3U;
/*
* First part of the processing with loop unrolling. Compute 8 outputs at a time.
*/
while (sample > 0U)
{
X0 = *pIn++;
X1 = *pIn++;
X2 = *pIn++;
X3 = *pIn++;
X4 = *pIn++;
X5 = *pIn++;
X6 = *pIn++;
X7 = *pIn++;
coeffs = vld1q(pCoeffs);
accVec = vmulq(coeffs, X7);
coeffs = vld1q(&pCoeffs[8]);
accVec = vfmaq(accVec, coeffs, X6);
coeffs = vld1q(&pCoeffs[16]);
accVec = vfmaq(accVec, coeffs, X5);
coeffs = vld1q(&pCoeffs[24]);
accVec = vfmaq(accVec, coeffs, X4);
coeffs = vld1q(&pCoeffs[32]);
accVec = vfmaq(accVec, coeffs, X3);
coeffs = vld1q(&pCoeffs[40]);
accVec = vfmaq(accVec, coeffs, X2);
coeffs = vld1q(&pCoeffs[48]);
accVec = vfmaq(accVec, coeffs, X1);
coeffs = vld1q(&pCoeffs[56]);
accVec = vfmaq(accVec, coeffs, X0);
coeffs = vld1q(&pCoeffs[64]);
accVec = vfmaq(accVec, coeffs, Xn1);
coeffs = vld1q(&pCoeffs[72]);
accVec = vfmaq(accVec, coeffs, Xn2);
coeffs = vld1q(&pCoeffs[80]);
accVec = vfmaq(accVec, coeffs, Yn1);
coeffs = vld1q(&pCoeffs[88]);
accVec = vfmaq(accVec, coeffs, Yn2);
/*
* Store the result in the accumulator in the destination buffer.
*/
vst1q(pOut, accVec);
pOut += 8;
/*
* update recurrence
*/
Xn1 = X7;
Xn2 = X6;
Yn1 = vgetq_lane(accVec, 7);
Yn2 = vgetq_lane(accVec, 6);
/*
* decrement the loop counter
*/
sample--;
}
/*
* If the blockSize is not a multiple of 8,
* compute any remaining output samples here.
*/
sample = blockSize & 0x7U;
if (sample)
{
/* save previous X, Y for modulo 1 length case */
lastX = X7;
lastY = Yn1;
X0 = *pIn++;
X1 = *pIn++;
X2 = *pIn++;
X3 = *pIn++;
X4 = *pIn++;
X5 = *pIn++;
X6 = *pIn++;
X7 = *pIn++;
coeffs = vld1q(pCoeffs);
accVec = vmulq(coeffs, X7);
coeffs = vld1q(&pCoeffs[8]);
accVec = vfmaq(accVec, coeffs, X6);
coeffs = vld1q(&pCoeffs[16]);
accVec = vfmaq(accVec, coeffs, X5);
coeffs = vld1q(&pCoeffs[24]);
accVec = vfmaq(accVec, coeffs, X4);
coeffs = vld1q(&pCoeffs[32]);
accVec = vfmaq(accVec, coeffs, X3);
coeffs = vld1q(&pCoeffs[40]);
accVec = vfmaq(accVec, coeffs, X2);
coeffs = vld1q(&pCoeffs[48]);
accVec = vfmaq(accVec, coeffs, X1);
coeffs = vld1q(&pCoeffs[56]);
accVec = vfmaq(accVec, coeffs, X0);
coeffs = vld1q(&pCoeffs[64]);
accVec = vfmaq(accVec, coeffs, Xn1);
coeffs = vld1q(&pCoeffs[72]);
accVec = vfmaq(accVec, coeffs, Xn2);
coeffs = vld1q(&pCoeffs[80]);
accVec = vfmaq(accVec, coeffs, Yn1);
coeffs = vld1q(&pCoeffs[88]);
accVec = vfmaq(accVec, coeffs, Yn2);
switch(sample)
{
case 1:
*pOut++ = vgetq_lane(accVec, 0);
Xn1 = X0;
Xn2 = lastX;
Yn1 = vgetq_lane(accVec, 0);
Yn2 = lastY;
break;
case 2:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
Xn1 = X1;
Xn2 = X0;
Yn1 = vgetq_lane(accVec, 1);
Yn2 = vgetq_lane(accVec, 0);
break;
case 3:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
*pOut++ = vgetq_lane(accVec, 2);
Xn1 = X2;
Xn2 = X1;
Yn1 = vgetq_lane(accVec, 2);
Yn2 = vgetq_lane(accVec, 1);
break;
case 4:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
*pOut++ = vgetq_lane(accVec, 2);
*pOut++ = vgetq_lane(accVec, 3);
Xn1 = X3;
Xn2 = X2;
Yn1 = vgetq_lane(accVec, 3);
Yn2 = vgetq_lane(accVec, 2);
break;
case 5:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
*pOut++ = vgetq_lane(accVec, 2);
*pOut++ = vgetq_lane(accVec, 3);
*pOut++ = vgetq_lane(accVec, 4);
Xn1 = X4;
Xn2 = X3;
Yn1 = vgetq_lane(accVec, 4);
Yn2 = vgetq_lane(accVec, 3);
break;
case 6:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
*pOut++ = vgetq_lane(accVec, 2);
*pOut++ = vgetq_lane(accVec, 3);
*pOut++ = vgetq_lane(accVec, 4);
*pOut++ = vgetq_lane(accVec, 5);
Xn1 = X5;
Xn2 = X4;
Yn1 = vgetq_lane(accVec, 5);
Yn2 = vgetq_lane(accVec, 4);
break;
case 7:
*pOut++ = vgetq_lane(accVec, 0);
*pOut++ = vgetq_lane(accVec, 1);
*pOut++ = vgetq_lane(accVec, 2);
*pOut++ = vgetq_lane(accVec, 3);
*pOut++ = vgetq_lane(accVec, 4);
*pOut++ = vgetq_lane(accVec, 5);
*pOut++ = vgetq_lane(accVec, 6);
Xn1 = X6;
Xn2 = X5;
Yn1 = vgetq_lane(accVec, 6);
Yn2 = vgetq_lane(accVec, 5);
break;
}
}
/*
* Store the updated state variables back into the pState array
*/
*pState++ = Xn1;
*pState++ = Xn2;
*pState++ = Yn1;
*pState++ = Yn2;
pCoeffs += sizeof(arm_biquad_mod_coef_f16) / sizeof(float16_t);
/*
* The first stage goes from the input buffer to the output buffer.
* Subsequent numStages occur in-place in the output buffer
*/
pIn = pDst;
/*
* Reset the output pointer
*/
pOut = pDst;
/*
* decrement the loop counter
*/
stage--;
}
while (stage > 0U);
}
#else
void arm_biquad_cascade_df1_f16(
const arm_biquad_casd_df1_inst_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
const float16_t *pIn = pSrc; /* Source pointer */
float16_t *pOut = pDst; /* Destination pointer */
float16_t *pState = S->pState; /* pState pointer */
const float16_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
float16_t acc; /* Accumulator */
float16_t b0, b1, b2, a1, a2; /* Filter coefficients */
float16_t Xn1, Xn2, Yn1, Yn2; /* Filter pState variables */
float16_t Xn; /* Temporary input */
uint32_t sample, stage = S->numStages; /* Loop counters */
do
{
/* Reading the coefficients */
b0 = *pCoeffs++;
b1 = *pCoeffs++;
b2 = *pCoeffs++;
a1 = *pCoeffs++;
a2 = *pCoeffs++;
/* Reading the pState values */
Xn1 = pState[0];
Xn2 = pState[1];
Yn1 = pState[2];
Yn2 = pState[3];
#if defined (ARM_MATH_LOOPUNROLL) && !defined(ARM_MATH_AUTOVECTORIZE)
/* Apply loop unrolling and compute 4 output values simultaneously. */
/* Variable acc hold output values that are being computed:
*
* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
*/
/* Loop unrolling: Compute 4 outputs at a time */
sample = blockSize >> 2U;
while (sample > 0U)
{
/* Read the first input */
Xn = *pIn++;
/* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
Yn2 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
/* Store output in destination buffer. */
*pOut++ = Yn2;
/* Every time after the output is computed state should be updated. */
/* The states should be updated as: */
/* Xn2 = Xn1 */
/* Xn1 = Xn */
/* Yn2 = Yn1 */
/* Yn1 = acc */
/* Read the second input */
Xn2 = *pIn++;
/* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
Yn1 = (b0 * Xn2) + (b1 * Xn) + (b2 * Xn1) + (a1 * Yn2) + (a2 * Yn1);
/* Store output in destination buffer. */
*pOut++ = Yn1;
/* Every time after the output is computed state should be updated. */
/* The states should be updated as: */
/* Xn2 = Xn1 */
/* Xn1 = Xn */
/* Yn2 = Yn1 */
/* Yn1 = acc */
/* Read the third input */
Xn1 = *pIn++;
/* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
Yn2 = (b0 * Xn1) + (b1 * Xn2) + (b2 * Xn) + (a1 * Yn1) + (a2 * Yn2);
/* Store output in destination buffer. */
*pOut++ = Yn2;
/* Every time after the output is computed state should be updated. */
/* The states should be updated as: */
/* Xn2 = Xn1 */
/* Xn1 = Xn */
/* Yn2 = Yn1 */
/* Yn1 = acc */
/* Read the forth input */
Xn = *pIn++;
/* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
Yn1 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn2) + (a2 * Yn1);
/* Store output in destination buffer. */
*pOut++ = Yn1;
/* Every time after the output is computed state should be updated. */
/* The states should be updated as: */
/* Xn2 = Xn1 */
/* Xn1 = Xn */
/* Yn2 = Yn1 */
/* Yn1 = acc */
Xn2 = Xn1;
Xn1 = Xn;
/* decrement loop counter */
sample--;
}
/* Loop unrolling: Compute remaining outputs */
sample = blockSize & 0x3U;
#else
/* Initialize blkCnt with number of samples */
sample = blockSize;
#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
while (sample > 0U)
{
/* Read the input */
Xn = *pIn++;
/* acc = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
/* Store output in destination buffer. */
*pOut++ = acc;
/* Every time after the output is computed state should be updated. */
/* The states should be updated as: */
/* Xn2 = Xn1 */
/* Xn1 = Xn */
/* Yn2 = Yn1 */
/* Yn1 = acc */
Xn2 = Xn1;
Xn1 = Xn;
Yn2 = Yn1;
Yn1 = acc;
/* decrement loop counter */
sample--;
}
/* Store the updated state variables back into the pState array */
*pState++ = Xn1;
*pState++ = Xn2;
*pState++ = Yn1;
*pState++ = Yn2;
/* The first stage goes from the input buffer to the output buffer. */
/* Subsequent numStages occur in-place in the output buffer */
pIn = pDst;
/* Reset output pointer */
pOut = pDst;
/* decrement loop counter */
stage--;
} while (stage > 0U);
}
/**
@} end of BiquadCascadeDF1 group
*/
#endif /* #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) */

@ -0,0 +1,158 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_df1_init_f16.c
* Description: Floating-point Biquad cascade DirectFormI(DF1) filter initialization function
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF1
@{
*/
/**
@brief Initialization function for the floating-point Biquad cascade filter.
@param[in,out] S points to an instance of the floating-point Biquad cascade structure.
@param[in] numStages number of 2nd order stages in the filter.
@param[in] pCoeffs points to the filter coefficients.
@param[in] pState points to the state buffer.
@return none
@par Coefficient and State Ordering
The coefficients are stored in the array <code>pCoeffs</code> in the following order:
<pre>
{b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
</pre>
@par
where <code>b1x</code> and <code>a1x</code> are the coefficients for the first stage,
<code>b2x</code> and <code>a2x</code> are the coefficients for the second stage,
and so on. The <code>pCoeffs</code> array contains a total of <code>5*numStages</code> values.
@par
The <code>pState</code> is a pointer to state array.
Each Biquad stage has 4 state variables <code>x[n-1], x[n-2], y[n-1],</code> and <code>y[n-2]</code>.
The state variables are arranged in the <code>pState</code> array as:
<pre>
{x[n-1], x[n-2], y[n-1], y[n-2]}
</pre>
The 4 state variables for stage 1 are first, then the 4 state variables for stage 2, and so on.
The state array has a total length of <code>4*numStages</code> values.
The state variables are updated after each block of data is processed; the coefficients are untouched.
@par For MVE code, an additional buffer of modified coefficients is required.
Its size is numStages and each element of this buffer has type arm_biquad_mod_coef_f16.
So, its total size is 96*numStages float16_t elements.
The initialization function which must be used is arm_biquad_cascade_df1_mve_init_f16.
*/
void arm_biquad_cascade_df1_init_f16(
arm_biquad_casd_df1_inst_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState)
{
/* Assign filter stages */
S->numStages = numStages;
/* Assign coefficient pointer */
S->pCoeffs = pCoeffs;
/* Clear state buffer and size is always 4 * numStages */
memset(pState, 0, (4U * (uint32_t) numStages) * sizeof(float16_t));
/* Assign state pointer */
S->pState = pState;
}
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
static void generateCoefsFastBiquadF16(float16_t b0, float16_t b1, float16_t b2, float16_t a1, float16_t a2,
arm_biquad_mod_coef_f16 * newCoef)
{
float32_t coeffs[8][12] = {
{0, 0, 0, 0, 0, 0, 0, b0, b1, b2, a1, a2},
{0, 0, 0, 0, 0, 0, b0, b1, b2, 0, a2, 0},
{0, 0, 0, 0, 0, b0, b1, b2, 0, 0, 0, 0},
{0, 0, 0, 0, b0, b1, b2, 0, 0, 0, 0, 0},
{0, 0, 0, b0, b1, b2, 0, 0, 0, 0, 0, 0},
{0, 0, b0, b1, b2, 0, 0, 0, 0, 0, 0, 0},
{0, b0, b1, b2, 0, 0, 0, 0, 0, 0, 0, 0},
{b0, b1, b2, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
for (int i = 0; i < 12; i++)
{
coeffs[1][i] += (a1 * coeffs[0][i]);
coeffs[2][i] += (a1 * coeffs[1][i]) + (a2 * coeffs[0][i]);
coeffs[3][i] += (a1 * coeffs[2][i]) + (a2 * coeffs[1][i]);
coeffs[4][i] += (a1 * coeffs[3][i]) + (a2 * coeffs[2][i]);
coeffs[5][i] += (a1 * coeffs[4][i]) + (a2 * coeffs[3][i]);
coeffs[6][i] += (a1 * coeffs[5][i]) + (a2 * coeffs[4][i]);
coeffs[7][i] += (a1 * coeffs[6][i]) + (a2 * coeffs[5][i]);
/*
* transpose
*/
newCoef->coeffs[i][0] = (float16_t) coeffs[0][i];
newCoef->coeffs[i][1] = (float16_t) coeffs[1][i];
newCoef->coeffs[i][2] = (float16_t) coeffs[2][i];
newCoef->coeffs[i][3] = (float16_t) coeffs[3][i];
newCoef->coeffs[i][4] = (float16_t) coeffs[4][i];
newCoef->coeffs[i][5] = (float16_t) coeffs[5][i];
newCoef->coeffs[i][6] = (float16_t) coeffs[6][i];
newCoef->coeffs[i][7] = (float16_t) coeffs[7][i];
}
}
void arm_biquad_cascade_df1_mve_init_f16(arm_biquad_casd_df1_inst_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
arm_biquad_mod_coef_f16 * pCoeffsMod,
float16_t * pState)
{
arm_biquad_cascade_df1_init_f16(S, numStages, (float16_t *)pCoeffsMod, pState);
/* Generate SIMD friendly modified coefs */
for (int i = 0; i < numStages; i++)
{
generateCoefsFastBiquadF16(pCoeffs[0], pCoeffs[1], pCoeffs[2], pCoeffs[3], pCoeffs[4], pCoeffsMod);
pCoeffs += 5;
pCoeffsMod++;
}
}
#endif
/**
@} end of BiquadCascadeDF1 group
*/

@ -0,0 +1,492 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_df2T_f16.c
* Description: Processing function for floating-point transposed direct form II Biquad cascade filter
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF2T
@{
*/
/**
@brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
@param[in] S points to an instance of the filter data structure
@param[in] pSrc points to the block of input data
@param[out] pDst points to the block of output data
@param[in] blockSize number of samples to process
@return none
*/
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
void arm_biquad_cascade_df2T_f16(
const arm_biquad_cascade_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
float16_t *pIn = (float16_t *)pSrc; /* source pointer */
float16_t Xn0, Xn1;
float16_t acc0, acc1;
float16_t *pOut = pDst; /* destination pointer */
float16_t *pState = S->pState; /* State pointer */
uint32_t sample, stage = S->numStages; /* loop counters */
float16_t const *pCurCoeffs = /* coefficient pointer */
(float16_t const *) S->pCoeffs;
f16x8_t b0Coeffs, a0Coeffs; /* Coefficients vector */
f16x8_t b1Coeffs, a1Coeffs; /* Modified coef. vector */
f16x8_t state; /* State vector */
do
{
/*
* temporary carry variable for feeding the 128-bit vector shifter
*/
uint32_t tmp = 0;
/*
* Reading the coefficients
* b0Coeffs = {b0, b1, b2, x, x, x, x, x}
* a0Coeffs = { x, a1, a2, x, x, x, x, x}
*/
b0Coeffs = vld1q(pCurCoeffs); pCurCoeffs += 2;
a0Coeffs = vld1q(pCurCoeffs); pCurCoeffs += 3;
/*
* Reading the state values
* state = {d1, d2, 0, 0, x, x, x, x}
*/
state = *(f16x8_t *) pState;
state = vsetq_lane((float16_t)0.0, state, 2);
state = vsetq_lane((float16_t)0.0, state, 3);
/* b1Coeffs = {0, b0, b1, b2, x, x, x, x} */
/* b1Coeffs = { x, x, a1, a2, x, x, x, x} */
b1Coeffs = (f16x8_t)vshlcq_s16((int16x8_t)b0Coeffs, &tmp, 16);
a1Coeffs = (f16x8_t)vshlcq_s16((int16x8_t)a0Coeffs, &tmp, 16);
sample = blockSize / 2;
/* unrolled 2 x */
while (sample > 0U)
{
/*
* Read 2 inputs
*/
Xn0 = *pIn++;
Xn1 = *pIn++;
/*
* 1st half:
* / acc1 \ / b0 \ / d1 \ / 0 \
* | d1 | | b1 | | d2 | | a1 |
* | d2 | | b2 | | 0 | | a2 |
* | x | = | x | * Xn1 + | x | + | x | x acc1
* ... ... ... ...
* \ x / \ x / \ x / \ x /
*/
state = vfmaq(state, b0Coeffs, Xn0);
acc0 = vgetq_lane(state, 0);
state = vfmaq(state, a0Coeffs, acc0);
state = vsetq_lane((float16_t)0.0, state, 3);
/*
* 2nd half:
* same as 1st half, but all vector elements shifted down.
* / x \ / x \ / x \ / x \
* | acc1 | | b0 | | d1 | | 0 |
* | d1 | | b1 | | d2 | | a1 |
* | d2 | | b2 | | 0 | | a2 |
* | x | = | x | * Xn1 + | x | + | x | x acc1
* ... ... ... ...
* \ x / \ x / \ x / \ x /
*/
state = vfmaq(state, b1Coeffs, Xn1);
acc1 = vgetq_lane(state, 1);
state = vfmaq(state, a1Coeffs, acc1);
/* move d1, d2 up + clearing */
/* expect dual move or long move */
state = vsetq_lane(vgetq_lane(state, 2), state, 0);
state = vsetq_lane(vgetq_lane(state, 3), state, 1);
state = vsetq_lane((float16_t)0.0, state, 2);
/*
* Store the results in the destination buffer.
*/
*pOut++ = acc0;
*pOut++ = acc1;
/*
* decrement the loop counter
*/
sample--;
}
/* compiler does not come back when enabled */
/*
* tail handling
*/
if (blockSize & 1)
{
Xn0 = *pIn++;
state = vfmaq_n_f16(state, b0Coeffs, Xn0);
acc0 = vgetq_lane(state, 0);
state = vfmaq_n_f16(state, a0Coeffs, acc0);
*pOut++ = acc0;
*pState++ = vgetq_lane(state, 1);
*pState++ = vgetq_lane(state, 2);
}
else
{
*pState++ = vgetq_lane(state, 0);
*pState++ = vgetq_lane(state, 1);
}
/*
* The current stage input is given as the output to the next stage
*/
pIn = pDst;
/*
* Reset the output working pointer
*/
pOut = pDst;
/*
* decrement the loop counter
*/
stage--;
}
while (stage > 0U);
}
#else
LOW_OPTIMIZATION_ENTER
void arm_biquad_cascade_df2T_f16(
const arm_biquad_cascade_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
const float16_t *pIn = pSrc; /* Source pointer */
float16_t *pOut = pDst; /* Destination pointer */
float16_t *pState = S->pState; /* State pointer */
const float16_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
float16_t acc1; /* Accumulator */
float16_t b0, b1, b2, a1, a2; /* Filter coefficients */
float16_t Xn1; /* Temporary input */
float16_t d1, d2; /* State variables */
uint32_t sample, stage = S->numStages; /* Loop counters */
do
{
/* Reading the coefficients */
b0 = pCoeffs[0];
b1 = pCoeffs[1];
b2 = pCoeffs[2];
a1 = pCoeffs[3];
a2 = pCoeffs[4];
/* Reading the state values */
d1 = pState[0];
d2 = pState[1];
pCoeffs += 5U;
#if defined (ARM_MATH_LOOPUNROLL)
/* Loop unrolling: Compute 16 outputs at a time */
sample = blockSize >> 4U;
while (sample > 0U) {
/* y[n] = b0 * x[n] + d1 */
/* d1 = b1 * x[n] + a1 * y[n] + d2 */
/* d2 = b2 * x[n] + a2 * y[n] */
/* 1 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 2 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 3 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 4 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 5 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 6 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 7 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 8 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 9 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 10 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 11 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 12 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 13 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 14 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 15 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* 16 */
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* decrement loop counter */
sample--;
}
/* Loop unrolling: Compute remaining outputs */
sample = blockSize & 0xFU;
#else
/* Initialize blkCnt with number of samples */
sample = blockSize;
#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
while (sample > 0U) {
Xn1 = *pIn++;
acc1 = b0 * Xn1 + d1;
d1 = b1 * Xn1 + d2;
d1 += a1 * acc1;
d2 = b2 * Xn1;
d2 += a2 * acc1;
*pOut++ = acc1;
/* decrement loop counter */
sample--;
}
/* Store the updated state variables back into the state array */
pState[0] = d1;
pState[1] = d2;
pState += 2U;
/* The current stage output is given as the input to the next stage */
pIn = pDst;
/* Reset the output working pointer */
pOut = pDst;
/* decrement loop counter */
stage--;
} while (stage > 0U);
}
LOW_OPTIMIZATION_EXIT
#endif /* #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE) */
/**
@} end of BiquadCascadeDF2T group
*/

@ -0,0 +1,111 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_df2T_init_f16.c
* Description: Initialization function for floating-point transposed direct form II Biquad cascade filter
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF2T
@{
*/
/**
@brief Initialization function for the floating-point transposed direct form II Biquad cascade filter.
@param[in,out] S points to an instance of the filter data structure.
@param[in] numStages number of 2nd order stages in the filter.
@param[in] pCoeffs points to the filter coefficients.
@param[in] pState points to the state buffer.
@return none
@par Coefficient and State Ordering
The coefficients are stored in the array <code>pCoeffs</code> in the following order
in the not Neon version.
<pre>
{b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
</pre>
@par
where <code>b1x</code> and <code>a1x</code> are the coefficients for the first stage,
<code>b2x</code> and <code>a2x</code> are the coefficients for the second stage,
and so on. The <code>pCoeffs</code> array contains a total of <code>5*numStages</code> values.
For Neon version, this array is bigger. If numstages = 4x + y, then the array has size:
32*x + 5*y
and it must be initialized using the function
arm_biquad_cascade_df2T_compute_coefs_f16 which is taking the
standard array coefficient as parameters.
But, an array of 8*numstages is a good approximation.
Then, the initialization can be done with:
<pre>
arm_biquad_cascade_df2T_init_f16(&SNeon, nbCascade, neonCoefs, stateNeon);
arm_biquad_cascade_df2T_compute_coefs_f16(&SNeon,nbCascade,coefs);
</pre>
@par In this example, neonCoefs is a bigger array of size 8 * numStages.
coefs is the standard array:
<pre>
{b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
</pre>
@par
The <code>pState</code> is a pointer to state array.
Each Biquad stage has 2 state variables <code>d1,</code> and <code>d2</code>.
The 2 state variables for stage 1 are first, then the 2 state variables for stage 2, and so on.
The state array has a total length of <code>2*numStages</code> values.
The state variables are updated after each block of data is processed; the coefficients are untouched.
*/
void arm_biquad_cascade_df2T_init_f16(
arm_biquad_cascade_df2T_instance_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState)
{
/* Assign filter stages */
S->numStages = numStages;
/* Assign coefficient pointer */
S->pCoeffs = pCoeffs;
/* Clear state buffer and size is always 2 * numStages */
memset(pState, 0, (2U * (uint32_t) numStages) * sizeof(float16_t));
/* Assign state pointer */
S->pState = pState;
}
/**
@} end of BiquadCascadeDF2T group
*/

@ -0,0 +1,426 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_stereo_df2T_f16.c
* Description: Processing function for floating-point transposed direct form II Biquad cascade filter. 2 channels
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF2T
@{
*/
/**
@brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
@param[in] S points to an instance of the filter data structure
@param[in] pSrc points to the block of input data
@param[out] pDst points to the block of output data
@param[in] blockSize number of samples to process
@return none
*/
#if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE)
void arm_biquad_cascade_stereo_df2T_f16(
const arm_biquad_cascade_stereo_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
float16_t *pIn = (float16_t *)pSrc; /* source pointer */
float16_t *pOut = pDst; /* destination pointer */
float16_t *pState = S->pState; /* State pointer */
const float16_t *pCoeffs = S->pCoeffs; /* coefficient pointer */
float16_t b0, b1, b2, a1, a2; /* Filter coefficients */
uint32_t sample, stage = S->numStages; /* loop counters */
static const uint16_t idx2[] = {2, 3, 8, 9, 2, 3, 8, 9};
f16x8_t aCoeffs, bCoeffs;
float16_t scratch[16];
uint16x8_t loadIdxVec;
uint16x8_t reshufledIdxVec;
uint16_t startIdx = 0;
f16x8_t stateVec0, stateVec1;
f16x8_t inVec;
/*
* {0, 1, 0, 1, 0, 1, 0, 1} generator
*/
loadIdxVec = viwdupq_u16(startIdx, 2, 1);
reshufledIdxVec = *(uint16x8_t *)&idx2;
/*
* scratch top clearing
* layout : [d1a d1b d2a d2b d1a d1b d2a d2b 0 0]
*/
scratch[8] = (float16_t)0.0;
scratch[9] = (float16_t)0.0;
do
{
/*
* Reading the coefficients
*/
b0 = *pCoeffs++;
b1 = *pCoeffs++;
b2 = *pCoeffs++;
a1 = *pCoeffs++;
a2 = *pCoeffs++;
/* aCoeffs = {a1 a1 a2 a2 a1 a1 a2 a2} */
aCoeffs = vdupq_n_f16(a1);
aCoeffs = vsetq_lane(a2, aCoeffs, 2);
aCoeffs = vsetq_lane(a2, aCoeffs, 3);
aCoeffs = vsetq_lane(a2, aCoeffs, 6);
aCoeffs = vsetq_lane(a2, aCoeffs, 7);
/* bCoeffs = {b1 b1 b2 b2 b1 b1 b2 b2} */
bCoeffs = vdupq_n_f16(b1);
bCoeffs = vsetq_lane(b2, bCoeffs, 2);
bCoeffs = vsetq_lane(b2, bCoeffs, 3);
bCoeffs = vsetq_lane(b2, bCoeffs, 6);
bCoeffs = vsetq_lane(b2, bCoeffs, 7);
/*
* Reading the state values
* Save into scratch
*/
*(f16x8_t *) scratch = *(f16x8_t *) pState;
sample = blockSize;
while (sample > 0U)
{
/*
* step 1
*
* 0 | acc1a = xn1a * b0 + d1a
* 1 | acc1b = xn1b * b0 + d1b
* 2 | acc1a = xn1a * b0 + d1a
* 3 | acc1b = xn1b * b0 + d1b
* 4 | <repeat>
* 5 | ...
*/
/*
* load {d1a, d1b, d1a, d1b, d1a, d1b, d1a, d1b}
*/
stateVec0 = vldrhq_gather_shifted_offset((float16_t const *) scratch, loadIdxVec);
/*
* load {in0 in1 in0 in1 in0 in1 in0 in1}
*/
inVec = vldrhq_gather_shifted_offset_f16(pIn, loadIdxVec);
stateVec0 = vfmaq(stateVec0, inVec, b0);
*pOut++ = vgetq_lane(stateVec0, 0);
*pOut++ = vgetq_lane(stateVec0, 1);
/*
* step 2
*
* 0 | d1a = b1 * xn1a + a1 * acc1a + d2a
* 1 | d1b = b1 * xn1b + a1 * acc1b + d2b
* 2 | d2a = b2 * xn1a + a2 * acc1a + 0
* 3 | d2b = b2 * xn1b + a2 * acc1b + 0
* 4 | <repeat>
* 5 | ...
*/
/*
* load {d2a, d2b, 0, 0, d2a, d2b, 0, 0}
*/
stateVec1 = vldrhq_gather_shifted_offset((float16_t const *) scratch, reshufledIdxVec);
stateVec1 = vfmaq(stateVec1, stateVec0, aCoeffs);
stateVec1 = vfmaq(stateVec1, inVec, bCoeffs);
*(f16x8_t *) scratch = stateVec1;
pIn = pIn + 2;
sample--;
}
/*
* Store the updated state variables back into the state array
*/
*pState++ = vgetq_lane(stateVec1, 0);
*pState++ = vgetq_lane(stateVec1, 1);
*pState++ = vgetq_lane(stateVec1, 2);
*pState++ = vgetq_lane(stateVec1, 3);
/*
* The current stage input is given as the output to the next stage
*/
pIn = pDst;
/*
* Reset the output working pointer
*/
pOut = pDst;
/*
* decrement the loop counter
*/
stage--;
}
while (stage > 0U);
}
#else
LOW_OPTIMIZATION_ENTER
void arm_biquad_cascade_stereo_df2T_f16(
const arm_biquad_cascade_stereo_df2T_instance_f16 * S,
const float16_t * pSrc,
float16_t * pDst,
uint32_t blockSize)
{
const float16_t *pIn = pSrc; /* Source pointer */
float16_t *pOut = pDst; /* Destination pointer */
float16_t *pState = S->pState; /* State pointer */
const float16_t *pCoeffs = S->pCoeffs; /* Coefficient pointer */
float16_t acc1a, acc1b; /* Accumulator */
float16_t b0, b1, b2, a1, a2; /* Filter coefficients */
float16_t Xn1a, Xn1b; /* Temporary input */
float16_t d1a, d2a, d1b, d2b; /* State variables */
uint32_t sample, stage = S->numStages; /* Loop counters */
do
{
/* Reading the coefficients */
b0 = pCoeffs[0];
b1 = pCoeffs[1];
b2 = pCoeffs[2];
a1 = pCoeffs[3];
a2 = pCoeffs[4];
/* Reading the state values */
d1a = pState[0];
d2a = pState[1];
d1b = pState[2];
d2b = pState[3];
pCoeffs += 5U;
#if defined (ARM_MATH_LOOPUNROLL)
/* Loop unrolling: Compute 8 outputs at a time */
sample = blockSize >> 3U;
while (sample > 0U) {
/* y[n] = b0 * x[n] + d1 */
/* d1 = b1 * x[n] + a1 * y[n] + d2 */
/* d2 = b2 * x[n] + a2 * y[n] */
/* 1 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 2 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 3 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 4 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 5 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 6 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 7 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* 8 */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
*pOut++ = acc1a;
*pOut++ = acc1b;
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* decrement loop counter */
sample--;
}
/* Loop unrolling: Compute remaining outputs */
sample = blockSize & 0x7U;
#else
/* Initialize blkCnt with number of samples */
sample = blockSize;
#endif /* #if defined (ARM_MATH_LOOPUNROLL) */
while (sample > 0U) {
/* Read the input */
Xn1a = *pIn++; /* Channel a */
Xn1b = *pIn++; /* Channel b */
/* y[n] = b0 * x[n] + d1 */
acc1a = (b0 * Xn1a) + d1a;
acc1b = (b0 * Xn1b) + d1b;
/* Store the result in the accumulator in the destination buffer. */
*pOut++ = acc1a;
*pOut++ = acc1b;
/* Every time after the output is computed state should be updated. */
/* d1 = b1 * x[n] + a1 * y[n] + d2 */
d1a = ((b1 * Xn1a) + (a1 * acc1a)) + d2a;
d1b = ((b1 * Xn1b) + (a1 * acc1b)) + d2b;
/* d2 = b2 * x[n] + a2 * y[n] */
d2a = (b2 * Xn1a) + (a2 * acc1a);
d2b = (b2 * Xn1b) + (a2 * acc1b);
/* decrement loop counter */
sample--;
}
/* Store the updated state variables back into the state array */
pState[0] = d1a;
pState[1] = d2a;
pState[2] = d1b;
pState[3] = d2b;
pState += 4U;
/* The current stage output is given as the input to the next stage */
pIn = pDst;
/* Reset the output working pointer */
pOut = pDst;
/* Decrement the loop counter */
stage--;
} while (stage > 0U);
}
LOW_OPTIMIZATION_EXIT
#endif /* #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) */
/**
@} end of BiquadCascadeDF2T group
*/

@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------
* Project: CMSIS DSP Library
* Title: arm_biquad_cascade_stereo_df2T_init_f16.c
* Description: Initialization function for floating-point transposed direct form II Biquad cascade filter
*
* $Date: 18. March 2020
* $Revision: V1.6.0
*
* Target Processor: Cortex-M cores
* -------------------------------------------------------------------- */
/*
* Copyright (C) 2010-2020 ARM Limited or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dsp/filtering_functions_f16.h"
/**
@ingroup groupFilters
*/
/**
@addtogroup BiquadCascadeDF2T
@{
*/
/**
@brief Initialization function for the floating-point transposed direct form II Biquad cascade filter.
@param[in,out] S points to an instance of the filter data structure.
@param[in] numStages number of 2nd order stages in the filter.
@param[in] pCoeffs points to the filter coefficients.
@param[in] pState points to the state buffer.
@return none
@par Coefficient and State Ordering
The coefficients are stored in the array <code>pCoeffs</code> in the following order:
<pre>
{b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
</pre>
@par
where <code>b1x</code> and <code>a1x</code> are the coefficients for the first stage,
<code>b2x</code> and <code>a2x</code> are the coefficients for the second stage,
and so on. The <code>pCoeffs</code> array contains a total of <code>5*numStages</code> values.
@par
The <code>pState</code> is a pointer to state array.
Each Biquad stage has 2 state variables <code>d1,</code> and <code>d2</code> for each channel.
The 2 state variables for stage 1 are first, then the 2 state variables for stage 2, and so on.
The state array has a total length of <code>2*numStages</code> values.
The state variables are updated after each block of data is processed; the coefficients are untouched.
*/
void arm_biquad_cascade_stereo_df2T_init_f16(
arm_biquad_cascade_stereo_df2T_instance_f16 * S,
uint8_t numStages,
const float16_t * pCoeffs,
float16_t * pState)
{
/* Assign filter stages */
S->numStages = numStages;
/* Assign coefficient pointer */
S->pCoeffs = pCoeffs;
/* Clear state buffer and size is always 4 * numStages */
memset(pState, 0, (4U * (uint32_t) numStages) * sizeof(float16_t));
/* Assign state pointer */
S->pState = pState;
}
/**
@} end of BiquadCascadeDF2T group
*/

@ -497,8 +497,7 @@ void merge_rfft_f16(
and we describe each algorithm in turn.
@par Floating-point
The main functions are \ref arm_rfft_fast_f16() and \ref arm_rfft_fast_init_f16().
The older functions \ref arm_rfft_f16() and \ref arm_rfft_init_f16() have been deprecated
but are still documented.
@par
The FFT of a real N-point sequence has even symmetry in the frequency domain.
The second half of the data equals the conjugate of the first half flipped in frequency.

@ -329,6 +329,7 @@ set(TESTSRC16
Source/Tests/BasicTestsF16.cpp
Source/Tests/ComplexTestsF16.cpp
Source/Tests/FIRF16.cpp
Source/Tests/BIQUADF16.cpp
Source/Tests/TransformCF16.cpp
Source/Tests/TransformRF16.cpp
)
@ -483,7 +484,9 @@ if(DOXYGEN_FOUND)
set(DOXYGEN_ENABLE_PREPROCESSING YES)
set(DOXYGEN_MACRO_EXPANSION YES)
set(DOXYGEN_EXPAND_ONLY_PREDEF YES)
set(DOXYGEN_PREDEFINED "ARM_FLOAT16_SUPPORTED=1 __ALIGNED(x)=")
set(DOXYGEN_QUIET YES)
set(DOXYGEN_EXCLUDE_PATTERNS "*/RTE/*")
set(DOXYGEN_PREDEFINED "ARM_FLOAT16_SUPPORTED=1;__ALIGNED(x)=")
set(DOXYGEN_EXAMPLE_PATH "${ROOT}/CMSIS/DSP/Examples/ARM")
set(DOXYGEN_IMAGE_PATH "${ROOT}/CMSIS/DoxyGen/DSP/src/images")
set(DOXYGEN_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/docs")

@ -15,7 +15,7 @@ sys.path.insert(0, parent_dir)
import PatternGeneration.DebugTools as d
f = "f32"
f = "f16"
inputPath = os.path.join(parent_dir,"Patterns","DSP","Filtering","BIQUAD","BIQUAD%s" % f.upper(),"BiquadInput1_%s.txt" % f )
refPath = os.path.join(parent_dir,"Patterns","DSP","Filtering","BIQUAD","BIQUAD%s" % f.upper(),"BiquadOutput1_%s.txt" % f)
@ -24,11 +24,11 @@ outputPath= os.path.join(parent_dir,"Output","DSP","Filtering","BIQUAD","BIQUAD%
inSig = d.readF32Pattern(inputPath)
inSig = d.readF16Pattern(inputPath)
refSig = d.readF32Pattern(refPath)
refSig = d.readF16Pattern(refPath)
sig = d.readF32Output(outputPath)
sig = d.readF16Output(outputPath)
figure()

@ -0,0 +1,30 @@
#include "Test.h"
#include "Pattern.h"
#include "dsp/filtering_functions_f16.h"
class BIQUADF16:public Client::Suite
{
public:
BIQUADF16(Testing::testID_t id);
virtual void setUp(Testing::testID_t,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr);
virtual void tearDown(Testing::testID_t,Client::PatternMgr *mgr);
private:
#include "BIQUADF16_decl.h"
Client::Pattern<float16_t> coefs;
Client::Pattern<float16_t> inputs;
Client::Pattern<int16_t> configs;
Client::LocalPattern<float16_t> output;
Client::LocalPattern<float16_t> state;
Client::LocalPattern<float16_t> debugstate;
Client::LocalPattern<float16_t> vecCoefs;
// Reference patterns are not loaded when we are in dump mode
Client::RefPattern<float16_t> ref;
arm_biquad_casd_df1_inst_f16 Sdf1;
arm_biquad_cascade_df2T_instance_f16 Sdf2T;
arm_biquad_cascade_stereo_df2T_instance_f16 SStereodf2T;
};

@ -3,7 +3,7 @@ import numpy as np
import itertools
import Tools
from scipy import signal
from pylab import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show,semilogx, semilogy
#from pylab import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show,semilogx, semilogy
import math
# Those patterns are used for tests and benchmarks.
@ -165,7 +165,8 @@ def writeTests(config,format):
config.writeInput(2,allsamples,"AllBiquadInputs")
config.writeInput(2,allcoefs,"AllBiquadCoefs")
config.writeReference(2,alloutputs,"AllBiquadRefs")
if format==0:
# Stereo version only for floats
if format==0 or format==16:
config.writeInput(2,allStereo,"AllBiquadStereoInputs")
config.writeReference(2,allStereoOutputs,"AllBiquadStereoRefs")
@ -177,6 +178,7 @@ def generatePatterns():
configf64=Tools.Config(PATTERNDIR,PARAMDIR,"f64")
configf32=Tools.Config(PATTERNDIR,PARAMDIR,"f32")
configf16=Tools.Config(PATTERNDIR,PARAMDIR,"f16")
configq31=Tools.Config(PATTERNDIR,PARAMDIR,"q31")
configq15=Tools.Config(PATTERNDIR,PARAMDIR,"q15")
#configq7=Tools.Config(PATTERNDIR,PARAMDIR,"q7")
@ -184,11 +186,13 @@ def generatePatterns():
writeBenchmarks(configf32)
writeBenchmarks(configf16)
writeBenchmarks(configq31)
writeBenchmarks(configq15)
writeBenchmarks(configf64)
writeTests(configf32,0)
writeTests(configf16,16)
writeTests(configq31,31)
writeTests(configq15,15)
writeTests(configf64,64)

@ -35,6 +35,10 @@ def readQ15Pattern(r):
def hex2float(h):
return(struct.unpack('<f', struct.pack('<I', int(h,16)))[0])
def hex2f16(h):
return(struct.unpack('<e', struct.pack('<H', int(h,16)))[0])
def readF32Pattern(r):
l = []
with open(r, 'r') as f:
@ -47,6 +51,18 @@ def readF32Pattern(r):
#print(l)
return(l)
def readF16Pattern(r):
l = []
with open(r, 'r') as f:
f.readline()
nb = int(f.readline())
for i in range(nb):
f.readline()
l.append(hex2f16(f.readline()))
l = (1.0*np.array(l))
#print(l)
return(l)
# Read the hex and interpret the sign
def hexToQ31(s):
r = int(s,0)
@ -75,6 +91,11 @@ def readF32Output(path):
sig = 1.0 * sig
return(sig)
def readF16Output(path):
sig = np.loadtxt(path, delimiter=',',dtype="float",converters= {0:hex2f16})
sig = 1.0 * sig
return(sig)
def SNR(ref,sig):
energy = np.dot(ref,np.conj(ref))
error = np.dot(ref-sig,np.conj(ref-sig))

@ -0,0 +1,38 @@
H
18
// 7
0x0007
// 7
0x0007
// 7
0x0007
// 16
0x0010
// 7
0x0007
// 23
0x0017
// 16
0x0010
// 7
0x0007
// 16
0x0010
// 16
0x0010
// 16
0x0010
// 23
0x0017
// 23
0x0017
// 7
0x0007
// 23
0x0017
// 16
0x0010
// 23
0x0017
// 23
0x0017

@ -0,0 +1,278 @@
H
138
// 0.090749
0x2dcf
// 0.297714
0x34c3
// 0.370079
0x35ec
// -0.866262
0xbaee
// -0.259039
0xb425
// 1.000000
0x3c00
// -0.203709
0xb285
// 0.409945
0x368f
// 0.220308
0x330d
// 0.353450
0x35a8
// 0.083264
0x2d54
// 0.228502
0x3350
// -0.350585
0xb59c
// -0.973292
0xbbc9
// -0.432201
0xb6ea
// 1.000000
0x3c00
// 0.309839
0x34f5
// 0.310404
0x34f7
// -0.070854
0xac89
// -0.051628
0xaa9c
// -0.233402
0xb378
// -0.947077
0xbb94
// 0.735409
0x39e2
// 0.039576
0x2911
// 0.699316
0x3998
// 0.265284
0x343f
// 0.445346
0x3720
// -0.537190
0xb84c
// 0.861497
0x3ae4
// 0.557314
0x3875
// 0.237799
0x339c
// -0.322095
0xb527
// -0.165577
0xb14c
// -0.268455
0xb44c
// -0.006206
0x9e5b
// -1.000000
0xbc00
// -0.013745
0xa30a
// -0.774303
0xba32
// 0.317359
0x3514
// -0.519577
0xb828
// -0.100633
0xae71
// 0.939298
0x3b84
// -0.346776
0xb58c
// 0.381445
0x361a
// 0.206790
0x329e
// -0.513704
0xb81c
// 0.290425
0x34a6
// 0.005856
0x1dff
// -0.473748
0xb794
// -0.698766
0xb997
// 1.000000
0x3c00
// -0.369518
0xb5ea
// 0.028168
0x2736
// 0.357675
0x35b9
// -0.329220
0xb544
// -1.000000
0xbc00
// 0.067369
0x2c50
// 0.192438
0x3228
// 0.324685
0x3532
// -0.413632
0xb69e
// 0.416429
0x36aa
// 0.584225
0x38ac
// -0.026223
0xa6b7
// 0.041304
0x2949
// 0.885800
0x3b16
// 0.146558
0x30b1
// -0.236656
0xb393
// -0.603413
0xb8d4
// -0.301536
0xb4d3
// 0.109928
0x2f09
// 0.007826
0x2002
// 0.034941
0x2879
// 0.850439
0x3ace
// -0.758509
0xba11
// -0.436978
0xb6fe
// -0.336321
0xb562
// -0.445521
0xb721
// -0.203202
0xb281
// 0.675144
0x3967
// 0.106155
0x2ecb
// 0.092040
0x2de4
// 0.994482
0x3bf5
// -0.045544
0xa9d4
// -0.358418
0xb5bc
// -0.193444
0xb231
// -0.059471
0xab9d
// -0.396584
0xb658
// 0.570043
0x388f
// -0.997927
0xbbfc
// 0.776540
0x3a36
// 0.195411
0x3241
// -1.000000
0xbc00
// 0.228484
0x3350
// 0.017410
0x2475
// 1.000000
0x3c00
// 0.297985
0x34c5
// -0.602862
0xb8d3
// 0.447394
0x3729
// -0.353440
0xb5a8
// 0.945340
0x3b90
// -0.347074
0xb58e
// -0.297577
0xb4c3
// 0.005284
0x1d69
// -0.340117
0xb571
// 0.612439
0x38e6
// -0.595780
0xb8c4
// -0.121373
0xafc5
// -0.171782
0xb17f
// 0.049832
0x2a61
// -0.030238
0xa7be
// 0.413893
0x369f
// -1.000000
0xbc00
// 0.487682
0x37ce
// -0.671832
0xb960
// 0.329843
0x3547
// 0.697000
0x3993
// -0.095198
0xae18
// -0.206269
0xb29a
// -0.158260
0xb110
// 0.284811
0x348f
// -0.120901
0xafbd
// -0.226450
0xb33f
// -0.122292
0xafd4
// -1.000000
0xbc00
// -0.071526
0xac94
// -0.329918
0xb547
// -0.243872
0xb3ce
// -0.076829
0xaceb
// -0.134285
0xb04c
// 0.096303
0x2e2a
// 0.690463
0x3986
// -0.108377
0xaef0
// 0.074647
0x2cc7
// 0.388592
0x3638
// -0.342842
0xb57c
// 0.024713
0x2654
// 0.424262
0x36ca
// 0.233694
0x337a

@ -0,0 +1,278 @@
H
138
// 0.001815
0x176f
// 0.013102
0x22b5
// 0.050462
0x2a76
// 0.117357
0x2f83
// 0.212805
0x32cf
// 0.318055
0x3517
// 0.390735
0x3640
// 0.008199
0x2033
// -0.001609
0x9697
// -0.003003
0x9a27
// -0.002836
0x99cf
// -0.012070
0xa22e
// -0.003203
0x9a8f
// -0.013196
0xa2c2
// 0.014895
0x23a0
// 0.050029
0x2a67
// 0.000281
0xc9b
// 0.000280
0xc96
// -0.029008
0xa76d
// -0.061102
0xabd2
// 0.023713
0x2612
// -0.016783
0xa44c
// 0.033921
0x2858
// 0.000792
0x127c
// 0.013547
0x22f0
// -0.002833
0x99cd
// -0.001966
0x9807
// -0.038247
0xa8e5
// 0.037007
0x28bd
// 0.026340
0x26be
// 0.033025
0x283a
// -0.073598
0xacb6
// -0.033348
0xa845
// 0.030677
0x27da
// 0.087663
0x2d9c
// -0.017550
0xa47e
// -0.044557
0xa9b4
// -0.064920
0xac28
// 0.093289
0x2df8
// -0.010463
0xa15b
// 0.023318
0x25f8
// -0.061756
0xabe8
// 0.027469
0x2708
// 0.004476
0x1c95
// -0.011275
0xa1c6
// -0.014503
0xa36d
// 0.005809
0x1df3
// -0.019942
0xa51b
// 0.008062
0x2021
// 0.018329
0x24b1
// 0.053388
0x2ad5
// -0.141675
0xb089
// 0.061354
0x2bda
// 0.007154
0x1f53
// -0.036437
0xa8aa
// 0.073284
0x2cb1
// -0.074470
0xacc4
// 0.022375
0x25ba
// 0.055790
0x2b24
// -0.152540
0xb0e2
// 0.271077
0x3456
// -0.367300
0xb5e0
// 0.397604
0x365d
// -0.364895
0xb5d7
// 0.282330
0x3484
// -0.146843
0xb0b3
// -0.011401
0xa1d6
// 0.158111
0x310f
// -0.300439
0xb4cf
// 0.002199
0x1881
// -0.003526
0x9b39
// 0.005121
0x1d3e
// 0.008457
0x2054
// -0.027763
0xa71b
// 0.030334
0x27c4
// -0.053217
0xaad0
// 0.111524
0x2f23
// -0.183862
0xb1e2
// 0.256535
0x341b
// -0.349516
0xb598
// 0.475543
0x379c
// -0.609063
0xb8df
// 0.737780
0x39e7
// -0.898172
0xbb2f
// 1.050245
0x3c33
// -1.141338
0xbc91
// 1.220336
0x3ce2
// -1.295086
0xbd2e
// 1.284482
0x3d23
// -1.186682
0xbcbf
// 1.064316
0x3c42
// -0.915268
0xbb52
// 0.004570
0x1cae
// -0.000526
0x904e
// 0.029017
0x276e
// 0.010748
0x2181
// 0.024511
0x2646
// 0.077049
0x2cee
// -0.038554
0xa8ef
// 0.018907
0x24d7
// -0.008229
0xa037
// -0.053503
0xaad9
// -0.089768
0xadbf
// 0.179527
0x31bf
// 0.262406
0x3433
// -0.006358
0x9e83
// -0.830097
0xbaa4
// -0.313696
0xb505
// 0.829726
0x3aa3
// 1.678080
0x3eb6
// -0.718775
0xb9c0
// -2.241017
0xc07b
// -1.360593
0xbd71
// 2.953462
0x41e8
// 2.624015
0x413f
// 0.013940
0x2323
// -0.056064
0xab2d
// 0.143494
0x3098
// -0.296188
0xb4bd
// 0.518200
0x3825
// -0.811617
0xba7e
// 1.163917
0x3ca8
// -1.557938
0xbe3b
// 1.965931
0x3fdd
// -2.357323
0xc0b7
// 2.693241
0x4163
// -2.938268
0xc1e0
// 3.080953
0x4229
// -3.129582
0xc242
// 3.109910
0x4238
// -3.048925
0xc219
// 2.937488
0x41e0
// -2.747077
0xc17f
// 2.434116
0x40de
// -1.973344
0xbfe5
// 1.373343
0x3d7e
// -0.662976
0xb94e
// -0.095482
0xae1c

@ -0,0 +1,554 @@
H
276
// 0.090749
0x2dcf
// -0.708719
0xb9ab
// 0.297714
0x34c3
// -0.277449
0xb470
// 0.370079
0x35ec
// 0.375403
0x3602
// -0.866262
0xbaee
// -0.619458
0xb8f5
// -0.259039
0xb425
// -0.355820
0xb5b1
// 1.000000
0x3c00
// -0.537893
0xb84e
// -0.203709
0xb285
// -1.000000
0xbc00
// 0.409945
0x368f
// 0.203932
0x3287
// 0.220308
0x330d
// 0.403046
0x3673
// 0.353450
0x35a8
// -0.209431
0xb2b4
// 0.083264
0x2d54
// 0.391242
0x3643
// 0.228502
0x3350
// 0.087217
0x2d95
// -0.350585
0xb59c
// -0.034302
0xa864
// -0.973292
0xbbc9
// -0.613797
0xb8e9
// -0.432201
0xb6ea
// 0.871068
0x3af8
// 1.000000
0x3c00
// 0.714341
0x39b7
// 0.309839
0x34f5
// -0.309662
0xb4f4
// 0.310404
0x34f7
// -0.807307
0xba75
// -0.070854
0xac89
// -0.514156
0xb81d
// -0.051628
0xaa9c
// -0.394304
0xb64f
// -0.233402
0xb378
// 1.000000
0x3c00
// -0.947077
0xbb94
// -0.238045
0xb39e
// 0.735409
0x39e2
// -0.280845
0xb47e
// 0.039576
0x2911
// 0.353686
0x35a9
// 0.699316
0x3998
// 0.663809
0x394f
// 0.265284
0x343f
// -0.221083
0xb313
// 0.445346
0x3720
// 0.791439
0x3a55
// -0.537190
0xb84c
// 0.079383
0x2d15
// 0.861497
0x3ae4
// 0.300728
0x34d0
// 0.557314
0x3875
// -0.582388
0xb8a9
// 0.237799
0x339c
// -0.483977
0xb7be
// -0.322095
0xb527
// -1.000000
0xbc00
// -0.165577
0xb14c
// 0.832347
0x3aa9
// -0.268455
0xb44c
// -0.958302
0xbbab
// -0.006206
0x9e5b
// -0.456989
0xb750
// -1.000000
0xbc00
// 0.064764
0x2c25
// -0.013745
0xa30a
// -0.401132
0xb66b
// -0.774303
0xba32
// 0.636107
0x3917
// 0.317359
0x3514
// 0.642728
0x3924
// -0.519577
0xb828
// -0.629144
0xb908
// -0.100633
0xae71
// 0.428129
0x36da
// 0.939298
0x3b84
// -0.396617
0xb659
// -0.346776
0xb58c
// -0.690538
0xb986
// 0.381445
0x361a
// 0.018973
0x24db
// 0.206790
0x329e
// 0.201425
0x3272
// -0.513704
0xb81c
// 0.050934
0x2a85
// 0.290425
0x34a6
// 0.466795
0x3778
// 0.005856
0x1dff
// 0.511943
0x3818
// -0.473748
0xb794
// 0.111088
0x2f1c
// -0.698766
0xb997
// -1.000000
0xbc00
// 1.000000
0x3c00
// 0.312244
0x34ff
// -0.369518
0xb5ea
// 0.672735
0x3962
// 0.028168
0x2736
// -0.287860
0xb49b
// 0.357675
0x35b9
// -0.388356
0xb637
// -0.329220
0xb544
// -0.472520
0xb78f
// -1.000000
0xbc00
// 0.267886
0x3449
// 0.067369
0x2c50
// -0.209743
0xb2b6
// 0.192438
0x3228
// -0.220904
0xb312
// 0.324685
0x3532
// 0.424196
0x36ca
// -0.413632
0xb69e
// 0.599550
0x38cc
// 0.416429
0x36aa
// 0.268697
0x344d
// 0.584225
0x38ac
// -0.332282
0xb551
// -0.026223
0xa6b7
// -0.517420
0xb824
// 0.041304
0x2949
// 0.359686
0x35c1
// 0.885800
0x3b16
// -1.000000
0xbc00
// 0.146558
0x30b1
// -0.593659
0xb8c0
// -0.236656
0xb393
// -0.686024
0xb97d
// -0.603413
0xb8d4
// 0.365216
0x35d8
// -0.301536
0xb4d3
// 0.250174
0x3401
// 0.109928
0x2f09
// -0.463528
0xb76b
// 0.007826
0x2002
// -0.608772
0xb8df
// 0.034941
0x2879
// 0.420709
0x36bb
// 0.850439
0x3ace
// 0.147446
0x30b8
// -0.758509
0xba11
// -0.596620
0xb8c6
// -0.436978
0xb6fe
// -0.370176
0xb5ec
// -0.336321
0xb562
// 0.732716
0x39dd
// -0.445521
0xb721
// -0.532015
0xb842
// -0.203202
0xb281
// -0.373343
0xb5f9
// 0.675144
0x3967
// 0.394178
0x364f
// 0.106155
0x2ecb
// 0.926086
0x3b69
// 0.092040
0x2de4
// -0.199343
0xb261
// 0.994482
0x3bf5
// 0.637415
0x3919
// -0.045544
0xa9d4
// 0.581201
0x38a6
// -0.358418
0xb5bc
// 1.000000
0x3c00
// -0.193444
0xb231
// 0.076861
0x2ceb
// -0.059471
0xab9d
// 0.343059
0x357d
// -0.396584
0xb658
// 0.286700
0x3496
// 0.570043
0x388f
// 0.443004
0x3717
// -0.997927
0xbbfc
// -0.582833
0xb8aa
// 0.776540
0x3a36
// 0.525510
0x3834
// 0.195411
0x3241
// -0.722763
0xb9c8
// -1.000000
0xbc00
// -0.101095
0xae78
// 0.228484
0x3350
// 1.000000
0x3c00
// 0.017410
0x2475
// -0.071477
0xac93
// 1.000000
0x3c00
// 0.257300
0x341e
// 0.297985
0x34c5
// -0.187492
0xb200
// -0.602862
0xb8d3
// -0.546540
0xb85f
// 0.447394
0x3729
// -0.851219
0xbacf
// -0.353440
0xb5a8
// -0.744304
0xb9f4
// 0.945340
0x3b90
// -0.304387
0xb4df
// -0.347074
0xb58e
// 0.463953
0x376c
// -0.297577
0xb4c3
// -0.557017
0xb875
// 0.005284
0x1d69
// 0.202782
0x327d
// -0.340117
0xb571
// -0.240348
0xb3b1
// 0.612439
0x38e6
// -0.360752
0xb5c6
// -0.595780
0xb8c4
// -0.536713
0xb84b
// -0.121373
0xafc5
// 0.706115
0x39a6
// -0.171782
0xb17f
// 0.496797
0x37f3
// 0.049832
0x2a61
// 0.939503
0x3b84
// -0.030238
0xa7be
// -0.205750
0xb296
// 0.413893
0x369f
// 0.997938
0x3bfc
// -1.000000
0xbc00
// 1.000000
0x3c00
// 0.487682
0x37ce
// 0.038016
0x28de
// -0.671832
0xb960
// 0.244601
0x33d4
// 0.329843
0x3547
// -0.460708
0xb75f
// 0.697000
0x3993
// 0.375596
0x3602
// -0.095198
0xae18
// -0.095721
0xae20
// -0.206269
0xb29a
// 0.113772
0x2f48
// -0.158260
0xb110
// -0.019964
0xa51c
// 0.284811
0x348f
// -0.179064
0xb1bb
// -0.120901
0xafbd
// -0.071954
0xac9b
// -0.226450
0xb33f
// -0.163844
0xb13e
// -0.122292
0xafd4
// -0.344171
0xb582
// -1.000000
0xbc00
// -0.294410
0xb4b6
// -0.071526
0xac94
// 0.058838
0x2b88
// -0.329918
0xb547
// -0.473193
0xb792
// -0.243872
0xb3ce
// -0.402083
0xb66f
// -0.076829
0xaceb
// -0.167620
0xb15d
// -0.134285
0xb04c
// 0.157760
0x310c
// 0.096303
0x2e2a
// 0.442752
0x3716
// 0.690463
0x3986
// 1.000000
0x3c00
// -0.108377
0xaef0
// 0.032234
0x2820
// 0.074647
0x2cc7
// -0.123645
0xafea
// 0.388592
0x3638
// 0.234767
0x3383
// -0.342842
0xb57c
// 0.036175
0x28a1
// 0.024713
0x2654
// -0.220100
0xb30b
// 0.424262
0x36ca
// 0.072053
0x2c9d
// 0.233694
0x337a
// -0.252993
0xb40c

@ -0,0 +1,554 @@
H
276
// 0.001815
0x176f
// -0.014174
0xa342
// 0.013102
0x22b5
// -0.061370
0xabdb
// 0.050462
0x2a76
// -0.167502
0xb15c
// 0.117357
0x2f83
// -0.364511
0xb5d5
// 0.212805
0x32cf
// -0.655909
0xb93f
// 0.318055
0x3517
// -1.035229
0xbc24
// 0.390735
0x3640
// -1.482338
0xbdee
// 0.008199
0x2033
// 0.004079
0x1c2d
// -0.001609
0x9697
// 0.005069
0x1d31
// -0.003003
0x9a27
// -0.013505
0xa2ea
// -0.002836
0x99cf
// 0.006342
0x1e7e
// -0.012070
0xa22e
// -0.002117
0x9856
// -0.003203
0x9a8f
// -0.016830
0xa44f
// -0.013196
0xa2c2
// 0.012093
0x2231
// 0.014895
0x23a0
// 0.013723
0x2307
// 0.050029
0x2a67
// 0.011803
0x220b
// 0.000281
0xc9b
// -0.009368
0xa0cc
// 0.000280
0xc96
// -0.022965
0xa5e1
// -0.029008
0xa76d
// -0.022791
0xa5d6
// -0.061102
0xabd2
// 0.006777
0x1ef0
// 0.023713
0x2612
// 0.066577
0x2c43
// -0.016783
0xa44c
// -0.016955
0xa457
// 0.033921
0x2858
// -0.021415
0xa57b
// 0.000792
0x127c
// 0.007074
0x1f3e
// 0.013547
0x22f0
// 0.009352
0x20ca
// -0.002833
0x99cd
// -0.015184
0xa3c6
// -0.001966
0x9807
// 0.001071
0x1463
// -0.038247
0xa8e5
// -0.012819
0xa290
// 0.037007
0x28bd
// 0.039871
0x291a
// 0.026340
0x26be
// -0.023873
0xa61d
// 0.033025
0x283a
// 0.000521
0x1044
// -0.073598
0xacb6
// -0.026483
0xa6c8
// -0.033348
0xa845
// 0.066472
0x2c41
// 0.030677
0x27da
// -0.012629
0xa277
// 0.087663
0x2d9c
// -0.017478
0xa479
// -0.017550
0xa47e
// -0.074405
0xacc3
// -0.044557
0xa9b4
// 0.055342
0x2b15
// -0.064920
0xac28
// 0.055921
0x2b28
// 0.093289
0x2df8
// 0.023341
0x25fa
// -0.010463
0xa15b
// -0.094355
0xae0a
// 0.023318
0x25f8
// -0.028858
0xa763
// -0.061756
0xabe8
// 0.000425
0xef9
// 0.027469
0x2708
// 0.103323
0x2e9d
// 0.004476
0x1c95
// -0.035916
0xa899
// -0.011275
0xa1c6
// 0.012297
0x224c
// -0.014503
0xa36d
// -0.067546
0xac53
// 0.005809
0x1df3
// 0.009336
0x20c8
// -0.019942
0xa51b
// -0.022002
0xa5a2
// 0.008062
0x2021
// -0.004300
0x9c67
// 0.018329
0x24b1
// 0.002702
0x1988
// 0.053388
0x2ad5
// 0.103960
0x2ea7
// -0.141675
0xb089
// -0.082736
0xad4c
// 0.061354
0x2bda
// -0.073437
0xacb3
// 0.007154
0x1f53
// -0.007767
0x9ff4
// -0.036437
0xa8aa
// 0.022963
0x25e1
// 0.073284
0x2cb1
// -0.026655
0xa6d3
// -0.074470
0xacc4
// -0.006313
0x9e77
// 0.022375
0x25ba
// 0.065442
0x2c30
// 0.055790
0x2b24
// -0.115593
0xaf66
// -0.152540
0xb0e2
// 0.138136
0x306c
// 0.271077
0x3456
// -0.132111
0xb03a
// -0.367300
0xb5e0
// 0.092439
0x2deb
// 0.397604
0x365d
// -0.030042
0xa7b1
// -0.364895
0xb5d7
// -0.013934
0xa322
// 0.282330
0x3484
// 0.003737
0x1ba7
// -0.146843
0xb0b3
// 0.041898
0x295d
// -0.011401
0xa1d6
// -0.110710
0xaf16
// 0.158111
0x310f
// 0.196983
0x324e
// -0.300439
0xb4cf
// -0.281946
0xb483
// 0.002199
0x1881
// -0.009271
0xa0bf
// -0.003526
0x9b39
// 0.003354
0x1adf
// 0.005121
0x1d3e
// 0.009060
0x20a3
// 0.008457
0x2054
// -0.004557
0x9caa
// -0.027763
0xa71b
// -0.019306
0xa4f1
// 0.030334
0x27c4
// -0.004159
0x9c42
// -0.053217
0xaad0
// 0.049405
0x2a53
// 0.111524
0x2f23
// -0.069559
0xac74
// -0.183862
0xb1e2
// 0.054895
0x2b07
// 0.256535
0x341b
// -0.111301
0xaf20
// -0.349516
0xb598
// 0.228760
0x3352
// 0.475543
0x379c
// -0.307685
0xb4ec
// -0.609063
0xb8df
// 0.360273
0x35c4
// 0.737780
0x39e7
// -0.495016
0xb7ec
// -0.898172
0xbb2f
// 0.699226
0x3998
// 1.050245
0x3c33
// -0.853804
0xbad5
// -1.141338
0xbc91
// 1.004755
0x3c05
// 1.220336
0x3ce2
// -1.217852
0xbcdf
// -1.295086
0xbd2e
// 1.491098
0x3df7
// 1.284482
0x3d23
// -1.692544
0xbec5
// -1.186682
0xbcbf
// 1.899790
0x3f99
// 1.064316
0x3c42
// -2.155018
0xc04f
// -0.915268
0xbb52
// 2.419751
0x40d7
// 0.004570
0x1cae
// 0.020000
0x251f
// -0.000526
0x904e
// -0.005254
0x9d61
// 0.029017
0x276e
// 0.045173
0x29c8
// 0.010748
0x2181
// 0.027089
0x26ef
// 0.024511
0x2646
// -0.014059
0xa333
// 0.077049
0x2cee
// 0.072648
0x2ca6
// -0.038554
0xa8ef
// -0.075313
0xacd2
// 0.018907
0x24d7
// -0.006088
0x9e3c
// -0.008229
0xa037
// 0.009693
0x20f7
// -0.053503
0xaad9
// 0.003691
0x1b8f
// -0.089768
0xadbf
// 0.015991
0x2418
// 0.179527
0x31bf
// -0.072120
0xac9e
// 0.262406
0x3433
// 0.025877
0x26a0
// -0.006358
0x9e83
// -0.010278
0xa143
// -0.830097
0xbaa4
// 0.223553
0x3327
// -0.313696
0xb505
// -0.178722
0xb1b8
// 0.829726
0x3aa3
// 0.030355
0x27c5
// 1.678080
0x3eb6
// -0.544499
0xb85b
// -0.718775
0xb9c0
// 0.529279
0x383c
// -2.241017
0xc07b
// -0.031781
0xa811
// -1.360593
0xbd71
// 1.213505
0x3cdb
// 2.953462
0x41e8
// -1.450980
0xbdce
// 2.624015
0x413f
// -0.169631
0xb16e
// 0.013940
0x2323
// 0.007512
0x1fb1
// -0.056064
0xab2d
// -0.031100
0xa7f6
// 0.143494
0x3098
// 0.085276
0x2d75
// -0.296188
0xb4bd
// -0.184716
0xb1e9
// 0.518200
0x3825
// 0.331244
0x354d
// -0.811617
0xba7e
// -0.524066
0xb831
// 1.163917
0x3ca8
// 0.744091
0x39f4
// -1.557938
0xbe3b
// -0.975890
0xbbcf
// 1.965931
0x3fdd
// 1.205644
0x3cd3
// -2.357323
0xc0b7
// -1.421765
0xbdb0
// 2.693241
0x4163
// 1.618968
0x3e7a
// -2.938268
0xc1e0
// -1.790631
0xbf2a
// 3.080953
0x4229
// 1.927714
0x3fb6
// -3.129582
0xc242
// -2.023565
0xc00c
// 3.109910
0x4238
// 2.080034
0x4029
// -3.048925
0xc219
// -2.090404
0xc02e
// 2.937488
0x41e0
// 2.045845
0x4017
// -2.747077
0xc17f
// -1.930276
0xbfb9
// 2.434116
0x40de
// 1.710973
0x3ed8
// -1.973344
0xbfe5
// -1.378252
0xbd83
// 1.373343
0x3d7e
// 0.932739
0x3b76
// -0.662976
0xb94e
// -0.392838
0xb649
// -0.095482
0xae1c
// -0.197429
0xb251

@ -0,0 +1,32 @@
H
15
// 0.020000
0x251f
// -0.021612
0xa588
// 0.020000
0x251f
// 1.744042
0x3efa
// -0.810000
0xba7b
// 1.000000
0x3c00
// -1.592168
0xbe5e
// 1.000000
0x3c00
// 1.746867
0x3efd
// -0.940900
0xbb87
// 1.000000
0x3c00
// -1.999600
0xc000
// 1.000000
0x3c00
// 1.957551
0x3fd5
// -0.960400
0xbbaf

@ -0,0 +1,202 @@
H
100
// -0.144249
0xb09e
// 0.510621
0x3816
// 0.384200
0x3626
// 0.297121
0x34c1
// 0.465464
0x3773
// 0.720142
0x39c3
// 0.704185
0x39a2
// 0.737929
0x39e7
// 0.176697
0x31a7
// -0.073951
0xacbc
// -0.031721
0xa80f
// -0.011387
0xa1d4
// -0.125405
0xb003
// -0.712307
0xb9b3
// -0.434647
0xb6f4
// -0.754246
0xba09
// -0.178077
0xb1b3
// -0.258859
0xb424
// -0.260711
0xb42c
// -0.440131
0xb70b
// 0.083380
0x2d56
// 0.514827
0x381e
// 0.569825
0x388f
// 0.211797
0x32c7
// 0.245181
0x33d9
// 0.689231
0x3984
// 0.777201
0x3a38
// 0.439377
0x3708
// -0.021818
0xa596
// 0.074712
0x2cc8
// -0.023099
0xa5ea
// 0.043241
0x2989
// -0.322836
0xb52a
// -0.680795
0xb972
// -0.476574
0xb7a0
// -0.422068
0xb6c1
// -0.212744
0xb2cf
// -0.538763
0xb84f
// -0.444250
0xb71c
// -0.282457
0xb485
// 0.323217
0x352c
// 0.464278
0x376e
// 0.515165
0x381f
// 0.286624
0x3496
// 0.091933
0x2de2
// 0.774396
0x3a32
// 0.800850
0x3a68
// 0.515716
0x3820
// -0.074704
0xacc8
// -0.056027
0xab2c
// 0.143090
0x3094
// -0.115615
0xaf66
// -0.254235
0xb411
// -0.676146
0xb969
// -0.756071
0xba0c
// -0.367983
0xb5e3
// -0.256397
0xb41a
// -0.656088
0xb940
// -0.473109
0xb792
// -0.146417
0xb0af
// 0.387297
0x3632
// 0.482898
0x37ba
// 0.367147
0x35e0
// 0.381028
0x3619
// 0.555917
0x3873
// 0.616368
0x38ee
// 0.538664
0x384f
// 0.441826
0x3712
// -0.024896
0xa660
// 0.050779
0x2a80
// -0.056459
0xab3a
// -0.136889
0xb061
// -0.498720
0xb7fb
// -1.000000
0xbc00
// -0.795695
0xba5e
// -0.240902
0xb3b5
// -0.281865
0xb483
// -0.455159
0xb748
// -0.456091
0xb74c
// 0.014021
0x232e
// 0.246737
0x33e5
// 0.483045
0x37bb
// 0.424827
0x36cc
// 0.487837
0x37ce
// 0.477279
0x37a3
// 0.724103
0x39cb
// 0.531910
0x3841
// 0.347106
0x358e
// 0.043309
0x298b
// 0.043867
0x299d
// 0.066014
0x2c3a
// -0.170294
0xb173
// -0.471979
0xb78d
// -0.734311
0xb9e0
// -0.697617
0xb995
// -0.145878
0xb0ab
// -0.226003
0xb33b
// -0.569424
0xb88e
// -0.545111
0xb85c
// 0.015754
0x2408

@ -0,0 +1,202 @@
H
100
// -0.002885
0x99e9
// 0.007973
0x2015
// 0.010700
0x217a
// 0.022029
0x25a4
// 0.043308
0x298b
// 0.073096
0x2cae
// 0.108205
0x2eed
// 0.153898
0x30ed
// 0.194828
0x323c
// 0.237055
0x3396
// 0.270469
0x3454
// 0.285325
0x3491
// 0.276622
0x346d
// 0.233367
0x3378
// 0.172596
0x3186
// 0.070814
0x2c88
// -0.038526
0xa8ee
// -0.169095
0xb169
// -0.293474
0xb4b2
// -0.405618
0xb67d
// -0.479463
0xb7ac
// -0.514691
0xb81e
// -0.503981
0xb808
// -0.447672
0xb72a
// -0.342482
0xb57b
// -0.200089
0xb267
// -0.042831
0xa97b
// 0.114341
0x2f51
// 0.255468
0x3416
// 0.371705
0x35f3
// 0.438956
0x3706
// 0.459807
0x375b
// 0.424364
0x36ca
// 0.342680
0x357c
// 0.230134
0x335d
// 0.089369
0x2db8
// -0.055734
0xab22
// -0.200869
0xb26e
// -0.318895
0xb51a
// -0.407629
0xb686
// -0.451154
0xb738
// -0.457062
0xb750
// -0.417601
0xb6ae
// -0.343442
0xb57f
// -0.241625
0xb3bb
// -0.109966
0xaf0a
// 0.019972
0x251d
// 0.147072
0x30b5
// 0.256096
0x3419
// 0.347010
0x358d
// 0.404973
0x367b
// 0.419371
0x36b6
// 0.399366
0x3664
// 0.337214
0x3565
// 0.245229
0x33d9
// 0.132619
0x303e
// 0.001704
0x16fa
// -0.137573
0xb067
// -0.258727
0xb424
// -0.359360
0xb5c0
// -0.423984
0xb6c9
// -0.451377
0xb739
// -0.433244
0xb6ef
// -0.368078
0xb5e4
// -0.262334
0xb433
// -0.128532
0xb01d
// 0.021721
0x258f
// 0.175190
0x319b
// 0.308574
0x34f0
// 0.419985
0x36b8
// 0.485403
0x37c4
// 0.503460
0x3807
// 0.466572
0x3777
// 0.377175
0x3609
// 0.253482
0x340e
// 0.104413
0x2eaf
// -0.062812
0xac05
// -0.221860
0xb319
// -0.355901
0xb5b2
// -0.447988
0xb72b
// -0.497125
0xb7f4
// -0.490949
0xb7db
// -0.435067
0xb6f6
// -0.330298
0xb549
// -0.192646
0xb22a
// -0.030410
0xa7c9
// 0.130262
0x302b
// 0.280811
0x347e
// 0.401810
0x366e
// 0.487299
0x37cc
// 0.526247
0x3836
// 0.514004
0x381d
// 0.455529
0x374a
// 0.355983
0x35b2
// 0.227491
0x3348
// 0.088057
0x2da3
// -0.062336
0xabfb
// -0.203164
0xb280
// -0.317837
0xb516
// -0.396032
0xb656

@ -0,0 +1,42 @@
H
20
// 0.077477
0x2cf5
// 0.989359
0x3bea
// -0.081363
0xad35
// 0.383844
0x3624
// 0.546921
0x3860
// 1.000000
0x3c00
// 0.661758
0x394b
// 0.964563
0x3bb7
// -0.540624
0xb853
// -0.582238
0xb8a8
// 0.572493
0x3894
// -0.161018
0xb127
// -0.276529
0xb46d
// -0.152652
0xb0e3
// 0.540633
0x3853
// -0.485720
0xb7c6
// -0.001937
0x97ef
// -0.993589
0xbbf3
// 0.565407
0x3886
// 0.392929
0x3649

@ -0,0 +1,449 @@
#include "BIQUADF16.h"
#include <stdio.h>
#include "Error.h"
#define SNR_THRESHOLD 32
/*
Reference patterns are generated with
a double precision computation.
*/
#define REL_ERROR (3.0e-3)
#define ABS_ERROR (3.5e-2)
void BIQUADF16::test_biquad_cascade_df1_ref()
{
float16_t *statep = state.ptr();
float16_t *debugstatep = debugstate.ptr();
const float16_t *coefsp = coefs.ptr();
const float16_t *inputp = inputs.ptr();
float16_t *outp = output.ptr();
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_biquad_mod_coef_f16 *coefsmodp = (arm_biquad_mod_coef_f16*)vecCoefs.ptr();
#endif
int blockSize;
/*
Python script is generating different tests with
different blockSize and numTaps.
We loop on those configs.
*/
blockSize = inputs.nbSamples() >> 1;
/*
The filter is initialized with the coefs, blockSize and numTaps.
*/
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_biquad_cascade_df1_mve_init_f16(&this->Sdf1,3,coefsp,coefsmodp,statep);
#else
arm_biquad_cascade_df1_init_f16(&this->Sdf1,3,coefsp,statep);
#endif
/*
Python script is filtering a 2*blockSize number of samples.
We do the same filtering in two pass to check (indirectly that
the state management of the fir is working.)
*/
arm_biquad_cascade_df1_f16(&this->Sdf1,inputp,outp,blockSize);
memcpy(debugstatep,statep,3*4*sizeof(float16_t));
debugstatep += 3*4;
outp += blockSize;
inputp += blockSize;
arm_biquad_cascade_df1_f16(&this->Sdf1,inputp,outp,blockSize);
outp += blockSize;
memcpy(debugstatep,statep,3*4*sizeof(float16_t));
debugstatep += 3*4;
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float16_t)SNR_THRESHOLD);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
}
void BIQUADF16::test_biquad_cascade_df2T_ref()
{
float16_t *statep = state.ptr();
float16_t *coefsp = coefs.ptr();
const float16_t *inputp = inputs.ptr();
float16_t *outp = output.ptr();
int blockSize;
/*
Python script is generating different tests with
different blockSize and numTaps.
We loop on those configs.
*/
blockSize = inputs.nbSamples() >> 1;
/*
The filter is initialized with the coefs, blockSize and numTaps.
*/
arm_biquad_cascade_df2T_init_f16(&this->Sdf2T,3,coefsp,statep);
/*
Python script is filtering a 2*blockSize number of samples.
We do the same filtering in two pass to check (indirectly that
the state management of the fir is working.)
*/
arm_biquad_cascade_df2T_f16(&this->Sdf2T,inputp,outp,blockSize);
outp += blockSize;
inputp += blockSize;
arm_biquad_cascade_df2T_f16(&this->Sdf2T,inputp,outp,blockSize);
outp += blockSize;
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float16_t)SNR_THRESHOLD);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
}
void BIQUADF16::test_biquad_cascade_df1_rand()
{
float16_t *statep = state.ptr();
const float16_t *coefsp = coefs.ptr();
const int16_t *configsp = configs.ptr();
const float16_t *inputp = inputs.ptr();
float16_t *outp = output.ptr();
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_biquad_mod_coef_f16 *coefsmodp = (arm_biquad_mod_coef_f16*)vecCoefs.ptr();
#endif
int blockSize;
int numStages;
unsigned long i;
for(i=0;i < configs.nbSamples(); i+=2)
{
/*
Python script is generating different tests with
different blockSize and numTaps.
We loop on those configs.
*/
numStages = configsp[0];
blockSize = configsp[1];
configsp += 2;
/*
The filter is initialized with the coefs, blockSize and numTaps.
*/
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
arm_biquad_cascade_df1_mve_init_f16(&this->Sdf1,numStages,coefsp,coefsmodp,statep);
#else
arm_biquad_cascade_df1_init_f16(&this->Sdf1,numStages,coefsp,statep);
#endif
/*
Python script is filtering a 2*blockSize number of samples.
We do the same filtering in two pass to check (indirectly that
the state management of the fir is working.)
*/
arm_biquad_cascade_df1_f16(&this->Sdf1,inputp,outp,blockSize);
inputp += blockSize;
outp += blockSize;
coefsp += numStages * 5;
}
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float16_t)SNR_THRESHOLD);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
}
void BIQUADF16::test_biquad_cascade_df2T_rand()
{
float16_t *statep = state.ptr();
const int16_t *configsp = configs.ptr();
float16_t *coefsp = coefs.ptr();
const float16_t *inputp = inputs.ptr();
float16_t *outp = output.ptr();
int blockSize;
int numStages;
unsigned long i;
for(i=0;i < configs.nbSamples(); i+=2)
{
/*
Python script is generating different tests with
different blockSize and numTaps.
We loop on those configs.
*/
numStages = configsp[0];
blockSize = configsp[1];
configsp += 2;
/*
The filter is initialized with the coefs, blockSize and numTaps.
*/
arm_biquad_cascade_df2T_init_f16(&this->Sdf2T,numStages,coefsp,statep);
coefsp += numStages * 5;
/*
Python script is filtering a 2*blockSize number of samples.
We do the same filtering in two pass to check (indirectly that
the state management of the fir is working.)
*/
arm_biquad_cascade_df2T_f16(&this->Sdf2T,inputp,outp,blockSize);
outp += blockSize;
inputp += blockSize;
}
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float16_t)SNR_THRESHOLD);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
}
void BIQUADF16::test_biquad_cascade_stereo_df2T_rand()
{
float16_t *statep = state.ptr();
const int16_t *configsp = configs.ptr();
const float16_t *coefsp = coefs.ptr();
const float16_t *inputp = inputs.ptr();
float16_t *outp = output.ptr();
int blockSize;
int numStages;
unsigned long i;
for(i=0;i < configs.nbSamples(); i+=2)
{
/*
Python script is generating different tests with
different blockSize and numTaps.
We loop on those configs.
*/
numStages = configsp[0];
blockSize = configsp[1];
configsp += 2;
/*
The filter is initialized with the coefs, blockSize and numTaps.
*/
arm_biquad_cascade_stereo_df2T_init_f16(&this->SStereodf2T,numStages,coefsp,statep);
coefsp += numStages * 5;
/*
Python script is filtering a 2*blockSize number of samples.
We do the same filtering in two pass to check (indirectly that
the state management of the fir is working.)
*/
arm_biquad_cascade_stereo_df2T_f16(&this->SStereodf2T,inputp,outp,blockSize);
outp += 2*blockSize;
inputp += 2*blockSize;
}
ASSERT_EMPTY_TAIL(output);
ASSERT_SNR(output,ref,(float16_t)SNR_THRESHOLD);
ASSERT_CLOSE_ERROR(output,ref,ABS_ERROR,REL_ERROR);
}
void BIQUADF16::setUp(Testing::testID_t id,std::vector<Testing::param_t>& params,Client::PatternMgr *mgr)
{
(void)params;
switch(id)
{
case BIQUADF16::TEST_BIQUAD_CASCADE_DF1_REF_1:
debugstate.create(2*64,BIQUADF16::STATE_F16_ID,mgr);
inputs.reload(BIQUADF16::BIQUADINPUTS_F16_ID,mgr);
coefs.reload(BIQUADF16::BIQUADCOEFS_F16_ID,mgr);
ref.reload(BIQUADF16::BIQUADREFS_F16_ID,mgr);
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
/* Max num stages is 47 in Python script */
vecCoefs.create(96*47,BIQUADF16::OUT_F16_ID,mgr);
#endif
break;
case BIQUADF16::TEST_BIQUAD_CASCADE_DF2T_REF_2:
vecCoefs.create(64,BIQUADF16::OUT_F16_ID,mgr);
inputs.reload(BIQUADF16::BIQUADINPUTS_F16_ID,mgr);
coefs.reload(BIQUADF16::BIQUADCOEFS_F16_ID,mgr);
ref.reload(BIQUADF16::BIQUADREFS_F16_ID,mgr);
break;
case BIQUADF16::TEST_BIQUAD_CASCADE_DF1_RAND_3:
inputs.reload(BIQUADF16::ALLBIQUADINPUTS_F16_ID,mgr);
coefs.reload(BIQUADF16::ALLBIQUADCOEFS_F16_ID,mgr);
ref.reload(BIQUADF16::ALLBIQUADREFS_F16_ID,mgr);
configs.reload(BIQUADF16::ALLBIQUADCONFIGS_S16_ID,mgr);
#if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
/* Max num stages is 47 in Python script */
vecCoefs.create(96*47,BIQUADF16::OUT_F16_ID,mgr);
#endif
break;
case BIQUADF16::TEST_BIQUAD_CASCADE_DF2T_RAND_4:
vecCoefs.create(512,BIQUADF16::OUT_F16_ID,mgr);
inputs.reload(BIQUADF16::ALLBIQUADINPUTS_F16_ID,mgr);
coefs.reload(BIQUADF16::ALLBIQUADCOEFS_F16_ID,mgr);
ref.reload(BIQUADF16::ALLBIQUADREFS_F16_ID,mgr);
configs.reload(BIQUADF16::ALLBIQUADCONFIGS_S16_ID,mgr);
break;
case BIQUADF16::TEST_BIQUAD_CASCADE_STEREO_DF2T_RAND_5:
inputs.reload(BIQUADF16::ALLBIQUADSTEREOINPUTS_F16_ID,mgr);
coefs.reload(BIQUADF16::ALLBIQUADCOEFS_F16_ID,mgr);
ref.reload(BIQUADF16::ALLBIQUADSTEREOREFS_F16_ID,mgr);
configs.reload(BIQUADF16::ALLBIQUADCONFIGS_S16_ID,mgr);
break;
}
output.create(ref.nbSamples(),BIQUADF16::OUT_F16_ID,mgr);
state.create(128,BIQUADF16::STATE_F16_ID,mgr);
}
void BIQUADF16::tearDown(Testing::testID_t id,Client::PatternMgr *mgr)
{
(void)id;
output.dump(mgr);
switch(id)
{
case BIQUADF16::TEST_BIQUAD_CASCADE_DF1_REF_1:
debugstate.dump(mgr);
break;
}
}

@ -166,6 +166,39 @@ group Root {
}
}
group BIQUAD {
class = BIQUAD
folder = BIQUAD
suite BIQUAD F16 {
class = BIQUADF16
folder = BIQUADF16
Pattern BIQUADINPUTS_F16_ID : BiquadInput1_f16.txt
Pattern BIQUADCOEFS_F16_ID : BiquadCoefs1_f16.txt
Pattern BIQUADREFS_F16_ID : BiquadOutput1_f16.txt
Pattern ALLBIQUADINPUTS_F16_ID : AllBiquadInputs2_f16.txt
Pattern ALLBIQUADSTEREOINPUTS_F16_ID : AllBiquadStereoInputs2_f16.txt
Pattern ALLBIQUADCOEFS_F16_ID : AllBiquadCoefs2_f16.txt
Pattern ALLBIQUADREFS_F16_ID : AllBiquadRefs2_f16.txt
Pattern ALLBIQUADSTEREOREFS_F16_ID : AllBiquadStereoRefs2_f16.txt
Pattern ALLBIQUADCONFIGS_S16_ID : AllBiquadConfigs2_s16.txt
Output OUT_F16_ID : Output
Output STATE_F16_ID : State
Functions {
arm_biquad_cascade_df1 ref pattern:test_biquad_cascade_df1_ref
arm_biquad_cascade_df2T ref pattern:test_biquad_cascade_df2T_ref
arm_biquad_cascade_df1 random pattern:test_biquad_cascade_df1_rand
arm_biquad_cascade_df2T random pattern:test_biquad_cascade_df2T_rand
arm_biquad_cascade_stereo_df2T random pattern:test_biquad_cascade_stereo_df2T_rand
}
}
}
}
group Transform Tests {

Loading…
Cancel
Save