277 lines
6.1 KiB
C
277 lines
6.1 KiB
C
/* ----------------------------------------------------------------------
|
|
* Copyright (C) 2010 ARM Limited. All rights reserved.
|
|
*
|
|
* $Date: 29. November 2010
|
|
* $Revision: V1.0.3
|
|
*
|
|
* Project: CMSIS DSP Library
|
|
*
|
|
* Title: math_helper.h
|
|
*
|
|
*
|
|
* Description: Prototypes of all helper functions required.
|
|
*
|
|
* Target Processor: Cortex-M4/Cortex-M3
|
|
*
|
|
* Version 1.0.3 2010/11/29
|
|
* Re-organized the CMSIS folders and updated documentation.
|
|
*
|
|
* Version 1.0.2 2010/11/11
|
|
* Documentation updated.
|
|
*
|
|
* Version 1.0.1 2010/10/05
|
|
* Production release and review comments incorporated.
|
|
*
|
|
* Version 1.0.0 2010/09/20
|
|
* Production release and review comments incorporated.
|
|
*
|
|
* Version 0.0.7 2010/06/10
|
|
* Misra-C changes done
|
|
* -------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* This file was imported from the ARM CMSIS-DSP library test suite and
|
|
* reworked for use in the Zephyr tests.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef MATH_HELPER_H
|
|
#define MATH_HELPER_H
|
|
|
|
#include <arm_math.h>
|
|
#ifdef CONFIG_CMSIS_DSP_FLOAT16
|
|
#include <arm_math_f16.h>
|
|
#endif
|
|
|
|
/**
|
|
* @brief Calculation of SNR
|
|
* @param float* Pointer to the reference buffer
|
|
* @param float* Pointer to the test buffer
|
|
* @param uint32_t total number of samples
|
|
* @return float SNR
|
|
* The function calculates signal to noise ratio for the reference output
|
|
* and test output
|
|
*/
|
|
|
|
/* If NaN, force SNR to 0.0 to ensure test will fail */
|
|
#define IFNANRETURNZERO(val) \
|
|
do { \
|
|
if (isnan((val))) { \
|
|
return 0.0; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define IFINFINITERETURN(val, def) \
|
|
do { \
|
|
if (isinf((val))) { \
|
|
if ((val) > 0) { \
|
|
return def; \
|
|
} else { \
|
|
return -def; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
static inline double arm_snr_f64(const double *pRef, const double *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
double EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
double SNR;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
/* Checking for a NAN value in pRef array */
|
|
IFNANRETURNZERO(pRef[i]);
|
|
|
|
/* Checking for a NAN value in pTest array */
|
|
IFNANRETURNZERO(pTest[i]);
|
|
|
|
EnergySignal += pRef[i] * pRef[i];
|
|
EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
|
|
}
|
|
|
|
/* Checking for a NAN value in EnergyError */
|
|
IFNANRETURNZERO(EnergyError);
|
|
|
|
SNR = 10 * log10(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
static inline float arm_snr_f32(const float *pRef, const float *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
float EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
/* Checking for a NAN value in pRef array */
|
|
IFNANRETURNZERO(pRef[i]);
|
|
|
|
/* Checking for a NAN value in pTest array */
|
|
IFNANRETURNZERO(pTest[i]);
|
|
|
|
EnergySignal += pRef[i] * pRef[i];
|
|
EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
|
|
}
|
|
|
|
/* Checking for a NAN value in EnergyError */
|
|
IFNANRETURNZERO(EnergyError);
|
|
|
|
|
|
SNR = 10 * log10f(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
#ifdef CONFIG_CMSIS_DSP_FLOAT16
|
|
static inline float arm_snr_f16(const float16_t *pRef, const float16_t *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
float EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
/* Checking for a NAN value in pRef array */
|
|
IFNANRETURNZERO((float)pRef[i]);
|
|
|
|
/* Checking for a NAN value in pTest array */
|
|
IFNANRETURNZERO((float)pTest[i]);
|
|
|
|
EnergySignal += pRef[i] * pRef[i];
|
|
EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]);
|
|
}
|
|
|
|
/* Checking for a NAN value in EnergyError */
|
|
IFNANRETURNZERO(EnergyError);
|
|
|
|
|
|
SNR = 10 * log10f(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
#endif /* CONFIG_CMSIS_DSP_FLOAT16 */
|
|
|
|
static inline float arm_snr_q63(const q63_t *pRef, const q63_t *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
double EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
double testVal, refVal;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
testVal = ((double)pTest[i]) / 9223372036854775808.0;
|
|
refVal = ((double)pRef[i]) / 9223372036854775808.0;
|
|
|
|
EnergySignal += refVal * refVal;
|
|
EnergyError += (refVal - testVal) * (refVal - testVal);
|
|
}
|
|
|
|
|
|
SNR = 10 * log10(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
static inline float arm_snr_q31(const q31_t *pRef, const q31_t *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
float EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
float32_t testVal, refVal;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
|
|
testVal = ((float32_t)pTest[i]) / 2147483648.0f;
|
|
refVal = ((float32_t)pRef[i]) / 2147483648.0f;
|
|
|
|
EnergySignal += refVal * refVal;
|
|
EnergyError += (refVal - testVal) * (refVal - testVal);
|
|
}
|
|
|
|
|
|
SNR = 10 * log10f(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
static inline float arm_snr_q15(const q15_t *pRef, const q15_t *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
float EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
float32_t testVal, refVal;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
testVal = ((float32_t)pTest[i]) / 32768.0f;
|
|
refVal = ((float32_t)pRef[i]) / 32768.0f;
|
|
|
|
EnergySignal += refVal * refVal;
|
|
EnergyError += (refVal - testVal) * (refVal - testVal);
|
|
}
|
|
|
|
SNR = 10 * log10f(EnergySignal / EnergyError);
|
|
|
|
/* Checking for a NAN value in SNR */
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
static inline float arm_snr_q7(const q7_t *pRef, const q7_t *pTest,
|
|
uint32_t buffSize)
|
|
{
|
|
float EnergySignal = 0.0, EnergyError = 0.0;
|
|
uint32_t i;
|
|
float SNR;
|
|
|
|
float32_t testVal, refVal;
|
|
|
|
for (i = 0; i < buffSize; i++) {
|
|
testVal = ((float32_t)pTest[i]) / 128.0f;
|
|
refVal = ((float32_t)pRef[i]) / 128.0f;
|
|
|
|
EnergySignal += refVal * refVal;
|
|
EnergyError += (refVal - testVal) * (refVal - testVal);
|
|
}
|
|
|
|
SNR = 10 * log10f(EnergySignal / EnergyError);
|
|
|
|
IFNANRETURNZERO(SNR);
|
|
IFINFINITERETURN(SNR, 100000.0);
|
|
|
|
return SNR;
|
|
}
|
|
|
|
#endif
|