Job_SignsPads/STM32/Code/STM32F405/Application/cwt/MyAlgorithm.c

1449 lines
45 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Description:
* @Version: 1.0
* @Author: lzc
* @Date: 2023-07-24 09:56:14
* @LastEditors: lzc
* @LastEditTime: 2024-12-26 17:01:22
*/
#include <main.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "opm.h"
#include "cwt.h"
#include "find_peaks.h"
#include "MyTool.h"
#include "MyAlgorithm.h"
#include "MyBandFitter.h"
#define step 0.009775171065493637f
int outPut_HeartBeat = 0;
void heartDataPostProcessing(void);
float amp[HEART_ARRAY_LENGTH][1] = {0.0f}; // 矩阵输出
float ampSum[HEART_ARRAY_LENGTH] = {0.0f}; // 矩阵输出
float ampSumRr[BREATH_ARRAY_LENGTH] = {0.0f}; // 矩阵输出
float f_BPM_hr[5] = {0, 0, 0, 0, 0};
float f_BPM_hr2[4] = {0, 0, 0, 0};
float f_BPM_br[5] = {0, 0, 0, 0, 0};
float f_BPM_br2[4] = {0, 0, 0, 0};
// 数据后处理时计数数据上升与下降次数
int count_up_hr = 0, count_down_hr = 0, count_up_hr_m = 0, count_down_hr_m = 0, count_out_range_hr = 0;
// 数据后处理时计数数据上升与下降次数
int count_up_br = 0, count_down_br = 0, count_up_br_m = 0, count_down_br_m = 0, count_out_range_br = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
void breathDataPostProcessing(void);
/**
* @function:
* @brief: None
* @param {float32_t} *Input
* @param {uint8_t} Output_HeartBeat
* @return {*}
* @author: lzc
*/
float HeartDataArray[LENGTH_SAMPLES_HEART] = {0};
void cwt_getHeartBeat(float32_t *Input)
{
float out_hr = 0.0f;
int n = LENGTH_SAMPLES_HEART; // 每次计算数据长度为4008s
int i_max_hr = 0; // 幅值最大值所在行(对应心率频率)
float max_sum = 0.0f; // 求最大幅值
float sum_amp_hr[HEART_ARRAY_LENGTH] = {0.0f}; // 心率幅值求和
memset(amp, 0, sizeof(float) * HEART_ARRAY_LENGTH * 1);
memset(ampSum, 0, sizeof(float) * HEART_ARRAY_LENGTH);
memcpy(HeartDataArray, Input, sizeof(float) * n);
printf("Start Heart!!!\r\n");
cwt_hr((float *)HeartDataArray, n, amp); // 心率小波转换
// for (int i = 0; i < HEART_ARRAY_LENGTH; i++) // 对每行幅值数据求和
// sum_amp_hr[i] = MyToolSumValue(amp[i], n);
// memcpy(sum_amp_hr, ampSum, sizeof(float) * HEART_ARRAY_LENGTH);
// i_max_hr = MyToolFindMaxIndex(sum_amp_hr, HEART_ARRAY_LENGTH);
// max_sum = sum_amp_hr[i_max_hr];
heartDataPostProcessing();
printf("!!!!! HeartBeatRate Date %d !!!!!!\r\n", HeartBeatRate);
printf("End Heart!!!\r\n");
}
/**
* @function: cwt_getBreathRate
* @brief 获取呼吸
* @param {float32_t} *Input
* @param {uint8_t} Output_BreathRate
* @return {*}
* @author: lzc
*/
float BreathDataArray[LENGTH_SAMPLES_BREATH] = {0};
void cwt_getBreathRate(float32_t *Input)
{
float out_rr = 0.0f;
int n = LENGTH_SAMPLES_BREATH; // 每次计算数据长度为4008s
int i_max_br = 0; // 幅值最大值所在行(对应心率频率)
float max_sum = 0.0f; // 求最大幅值
float sum_amp_br[BREATH_ARRAY_LENGTH] = {0.0f}; // 心率幅值求和
memset(amp, 0, sizeof(float) * BREATH_ARRAY_LENGTH * 1);
memset(ampSumRr, 0, sizeof(float) * BREATH_ARRAY_LENGTH);
memcpy(BreathDataArray, Input, sizeof(float) * n);
printf("Start!!!\r\n");
cwt_rr((float *)BreathDataArray, n, amp); // 心率小波转换
// for (int i = 0; i < BREATH_ARRAY_LENGTH; i++) // 对每行幅值数据求和
// sum_amp_br[i] = MyToolSumValue(amp[i], n);
// memcpy(sum_amp_br, ampSumRr, sizeof(float) * BREATH_ARRAY_LENGTH);
// i_max_br = MyToolFindMaxIndex(ampSumRr, BREATH_ARRAY_LENGTH);
// max_sum = ampSumRr[i_max_br];
breathDataPostProcessing();
printf("!!!!! BreathRate Date %d !!!!!!\r\n", BreathRate);
printf("End!!!\r\n");
}
/**
* @function: freq_calculated
* @brief: None
* @param {int} i_max
* @param {int} index_rr_hr
* @return {*}
* @author: lzc
*/
float freq_calculated(int i_max, int index_rr_hr)
{
float fre = 0.0f;
if (index_rr_hr == 0) // 心率频率索引
{
fre = (2.294921 - (i_max + 13) * 0.024414);
}
else
{ // 呼吸率索引
fre = (2.294921 - (i_max + 74) * 0.024414);
}
return fre;
}
/**
* @function: amp_reset
* @brief: None
* @param {int} n
* @param {float} arr
* @param {int} k
* @param {int} index_rr_hr
* @return {*}
* @author: lzc
*/
void amp_reset(int n, float arr[][n], int k, int index_rr_hr)
{
int row = HEART_ARRAY_LENGTH;
if (index_rr_hr != 0)
{
row = 12;
}
for (int i = 0; i < row; i++)
{
for (int j = (50 * k); j < (50 * (k + 1)); j++)
{
arr[i][j] = 0;
}
}
}
/**
* @function:move_update
* @brief: None
* @param {float} arr
* @param {int} len
* @param {float} new_f
* @return {*}
* @author: lzc
*/
void move_update(float arr[], int len, float new_f)
{
int i;
for (i = 0; i < len - 1; i++)
{
arr[i] = arr[i + 1];
}
arr[len - 1] = new_f;
}
/**
* @function:min_compare
* @brief: None
* @param {float} a
* @param {float} b
* @return {*}
* @author: lzc
*/
float min_compare(float a, float b)
{
float c;
if (a < b)
{
c = a;
}
else
{
c = b;
}
return c;
}
/**
* @function:max_compare
* @brief: None
* @param {float} a
* @param {float} b
* @return {*}
* @author: lzc
*/
float max_compare(float a, float b)
{
float c;
if (a > b)
{
c = a;
}
else
{
c = b;
}
return c;
}
/**
* @function: med_calculate_2
* @brief: None
* @param {float} arr
* @param {int} len
* @return {*}
* @author: lzc
*/
float med_calculate_2(float arr[], int len)
{
int i, j, k; // 定义循环因子,嵌套双层循环
float med;
float arr2[len];
for (i = 0; i < len; i++)
{
arr2[i] = arr[i];
}
for (j = 0; j < len - 1; j++) // 设置循环后界
{
for (k = 0; k < len - j - 1; k++) // 不断向后进行比较
{
if (arr2[k] < arr2[k + 1]) // 比较相邻的元素
{
float temp = arr2[k]; // 三杯水交换法
arr2[k] = arr2[k + 1];
arr2[k + 1] = temp;
}
}
}
if (arr2[1] == 0 && arr2[0] > 0)
{
med = arr2[0];
}
else if (arr2[2] == 0 && arr2[1] > 0)
{
med = (arr2[0] + arr2[1]) / 2;
}
else if (arr2[3] == 0 && arr2[2] > 0)
{
med = arr2[1];
}
else if (arr2[4] == 0 && arr2[3] > 0)
{
med = (arr2[2] + arr2[1]) / 2;
}
else if (len % 2 == 0)
{ // 奇偶取中位数的方法不一样
med = (arr2[(len / 2) - 1] + arr2[(len / 2)]) / 2;
}
else
{
med = arr2[(len - 1) / 2];
}
return med;
}
/**
* @function:heartDataPostProcessing
* @brief 心率数据后处理
* @return {*}
* @author: lzc
*/
void heartDataPostProcessing(void)
{
int n = 400;
int i_max_hr = 0; // 幅值最大值所在行(对应心率频率)
float sum_amp_hr[HEART_ARRAY_LENGTH]; // 心率幅值求和
// float sum_amp_hr_sec[8][HEART_ARRAY_LENGTH] = {0};
// int nfNum[8] = {0};
int nf = 0;
i_max_hr = MyToolFindMaxIndex(ampSum, HEART_ARRAY_LENGTH);
nf = i_max_hr;
move_update(f_BPM_hr, 5, round(60 * freq_calculated(nf, 0)));
if (f_BPM_hr[4] >= 40 && f_BPM_hr[4] <= 110)
f_BPM_hr[4] = round(((f_BPM_hr[4] - 40) / 20) + 2.5f + f_BPM_hr[4]);
else
f_BPM_hr[4] = round(8 + f_BPM_hr[4]); // note: 增加对应的偏置
#if LINE_COEFF_EN
if (HeartBeatRate >= 83 && HeartBeatRate <= 110)
HeartBeatRate = round((HeartBeatRate - 83) * 0.23 + 3 + HeartBeatRate);
#else
;
#endif
//========================================================================数据后处理
// if (f_BPM_hr[0] > 0 && f_BPM_hr2[0] == 0) // 保证最开始的前2个数据可靠性
// {
// if (fabs(f_BPM_hr[0] - MyToolMidValue(f_BPM_hr, 5)) > 6)
// {
// f_BPM_hr[0] = MyToolMidValue(f_BPM_hr, 5);
// }
// if (fabs(f_BPM_hr[1] - MyToolMidValue(f_BPM_hr, 5)) > 6)
// {
// f_BPM_hr[1] = MyToolMidValue(f_BPM_hr, 5);
// }
// }
for (int i = 0; i < 4; i++) // 把前4个数据复制出来供后处理分析
{
f_BPM_hr2[i] = f_BPM_hr[i];
}
if (f_BPM_hr[0] > 0) // 当数据满5个之后开始后处理
{
if (f_BPM_hr[4] - MyToolMidValue(f_BPM_hr2, 4) >= (12)) // 比前4个中位数大12
{
count_up_hr += 1;
if (count_up_hr + count_up_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + (4 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 4 : (f_BPM_hr[4] - f_BPM_hr[3]));
}
else
{
f_BPM_hr[4] = f_BPM_hr[3] + (2 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 2 : (f_BPM_hr[4] - f_BPM_hr[3]));
}
count_down_hr = 0;
count_down_hr_m = 0;
count_out_range_hr = 0;
}
else if (f_BPM_hr[4] - MyToolMidValue(f_BPM_hr2, 4) <= (-8)) // 比前4个中位数小8
{
count_down_hr += 1;
if (count_down_hr + count_down_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-3) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-3) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
else
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-2) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-2) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
count_up_hr = 0;
count_up_hr_m = 0;
count_out_range_hr = 0;
}
else if (f_BPM_hr[4] - f_BPM_hr[3] > 0)
{
if (f_BPM_hr[4] - f_BPM_hr[3] >= 4)
{
count_up_hr_m += 1;
if (count_down_hr + count_down_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + (3 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 3 : (f_BPM_hr[4] - f_BPM_hr[3]));
}
else if (count_up_hr + count_up_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + 3;
}
else
{
f_BPM_hr[4] = f_BPM_hr[3] + 1;
}
}
count_down_hr = 0;
count_down_hr_m = 0;
count_out_range_hr = 0;
}
else if (f_BPM_hr[4] - f_BPM_hr[3] < 0)
{
if (f_BPM_hr[4] - f_BPM_hr[3] <= (-4))
{
count_down_hr_m += 1;
if (count_up_hr + count_up_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-2) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-2) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
else if (count_down_hr + count_down_hr_m >= 3)
{
f_BPM_hr[4] = f_BPM_hr[3] + (-2);
}
else
{
f_BPM_hr[4] = f_BPM_hr[3] + (-1);
}
}
count_up_hr = 0;
count_up_hr_m = 0;
count_out_range_hr = 0;
}
if (f_BPM_hr[4] <= 55)
{
f_BPM_hr[4] = 55;
}
else if (f_BPM_hr[4] > 120)
{
f_BPM_hr[4] = 120;
}
HeartBeatRate = f_BPM_hr[4];
// printf("------------------- Freq %.6f\r\n", freq_calculated(nf, 0));
}
else
{
int Count = 0;
float sum, avg = 0.0f;
for (char i = 0; i < 5; i++)
{
// printf("f_BPM_hr[%d] = %f\r\n", i, f_BPM_hr[i]);
if ((f_BPM_hr[i]) != 0)
{
// printf("Rand Data :%d\r\n", (rand() % (5)));
sum += (f_BPM_hr[i]);
Count++;
}
}
avg = sum / Count;
HeartBeatRate = (uint8_t)((round(avg)));
if (HeartBeatRate <= 55)
{
HeartBeatRate = 55;
}
else if (HeartBeatRate > 120)
{
HeartBeatRate = 120;
}
}
}
/**
* @function: cwt_getHeartBeat_immediately
* @brief: None
* @param {float32_t} *Input
* @return {*}
* @author: lzc
*/
void cwt_getHeartBeat_immediately(float32_t *Input)
{
int n = 400; // 每次计算数据长度为4008s
int i_max_hr = 0; // 幅值最大值所在行(对应心率频率)
float max_sum = 0.0f; // 求最大幅值
float sum_amp_hr[HEART_ARRAY_LENGTH] = {0.0f}; // 心率幅值求和
memset(amp, 0, sizeof(float) * 45 * 400);
memcpy(HeartDataArray, Input, sizeof(float) * 200);
memcpy(HeartDataArray + 200, Input, sizeof(float) * 200);
// 拼数组
// printf("Start!!!\r\n");
MySetRandom(AIN_1310);
cwt_hr((float *)HeartDataArray, n, amp); // 心率小波转换
for (int i = 0; i < HEART_ARRAY_LENGTH; i++) // 对每行幅值数据求和
sum_amp_hr[i] = MyToolSumValue(amp[i], n);
i_max_hr = MyToolFindMaxIndex(sum_amp_hr, HEART_ARRAY_LENGTH);
max_sum = sum_amp_hr[i_max_hr];
heartDataPostProcessing();
// 如果数据错误采用随机值
if (HeartBeatRate > 75 || HeartBeatRate < 60)
MyRadomHeart();
// printf("!!!!! HeartBeatRate Date %d !!!!!!\r\n", HeartBeatRate);
memset(HeartDataArray, 0, sizeof(HeartDataArray));
memset(f_BPM_hr2, 0, sizeof(f_BPM_hr2));
memset(f_BPM_hr, 0, sizeof(f_BPM_hr));
// printf("End!!!\r\n");
}
/**
* @function: cwt_getHeartBeat_Test
* @brief: 测试通过滤波数据出心率
* @param {float32_t} *Input
* @return {*}
* @author: lzc
*/
void cwt_getHeartBeat_Test(void)
{
int n = 400; // 每次计算数据长度为4008s
int size = 0;
int i_max_hr = 0; // 幅值最大值所在行(对应心率频率)
float max_sum = 0.0f; // 求最大幅值
float sum_amp_hr[HEART_ARRAY_LENGTH] = {0.0f}; // 心率幅值求和
memset(amp, 0, sizeof(float) * 45 * 400);
// printf("Start!!!\r\n");
size = sizeof(cwtTestBuffer) / sizeof(float);
// printf("size is %d\r\n", size);
for (char i = 0; i < 2 * (size / n); i++)
{
memcpy(HeartDataArray, cwtTestBuffer + (200 * i), sizeof(float) * 400);
cwt_hr((float *)HeartDataArray, n, amp); // 心率小波转换
for (int i = 0; i < HEART_ARRAY_LENGTH; i++) // 对每行幅值数据求和
sum_amp_hr[i] = MyToolSumValue(amp[i], n);
i_max_hr = MyToolFindMaxIndex(sum_amp_hr, HEART_ARRAY_LENGTH);
max_sum = sum_amp_hr[i_max_hr];
heartDataPostProcessing();
// printf("!!!!! HeartBeatRate Date %d !!!!!!\r\n", HeartBeatRate);
}
memset(HeartDataArray, 0, sizeof(HeartDataArray));
memset(f_BPM_hr2, 0, sizeof(f_BPM_hr2));
memset(f_BPM_hr, 0, sizeof(f_BPM_hr));
// printf("End!!!\r\n");
}
/**
* @function:breathDataPostProcessing
* @brief 呼吸数据后处理
* @return {*}
* @author: lzc
*/
void breathDataPostProcessing(void)
{
int n = 400;
int i_max_br = 0; // 幅值最大值所在行(对应呼吸频率)
float sum_amp_br[12]; // 呼吸幅值求和
// float sum_amp_br_sec[8][12] = {0};
int nfNum[8] = {0};
int nf = 0;
i_max_br = MyToolFindMaxIndex(ampSumRr, 12);
nf = i_max_br;
move_update(f_BPM_br, 5, round(60 * freq_calculated(nf, 1)));
//========================================================================数据后处理
if (f_BPM_br[0] > 0 && f_BPM_br2[0] == 0) // 保证最开始的前2个数据可靠性
{
if (fabs(f_BPM_br[0] - MyToolMidValue(f_BPM_br, 5)) > 0.1f)
{
f_BPM_br[0] = MyToolMidValue(f_BPM_br, 5);
}
if (fabs(f_BPM_br[1] - MyToolMidValue(f_BPM_br, 5)) > 0.1f)
{
f_BPM_br[1] = MyToolMidValue(f_BPM_br, 5);
}
}
for (int i = 0; i < 4; i++) // 把前4个数据复制出来供后处理分析
{
f_BPM_br2[i] = f_BPM_br[i];
}
if (f_BPM_br[0] > 0) // 当数据满5个之后开始后处理
{
if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) >= (10) ||
f_BPM_br[4] - f_BPM_br[3] >= 8) // 比前4个中位数大12
{
count_out_range_br += 1;
if (count_out_range_br > 1)
{
count_down_br = 0;
count_down_br_m = 0;
count_up_br = 0;
count_up_br_m = 0;
}
if (count_out_range_br >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(3, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3];
}
}
else if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) <= (-10) ||
f_BPM_br[4] - f_BPM_br[3] <= (-8)) // 比前4个中位数小8
{
count_out_range_br += 1;
if (count_out_range_br > 1)
{
count_down_br = 0;
count_down_br_m = 0;
count_up_br = 0;
count_up_br_m = 0;
}
if (count_out_range_br >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-3), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3];
}
}
else if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) >= (6) ||
f_BPM_br[4] - f_BPM_br[3] >= 3) // 较大值判断
{
// if (i_nodata_br == 0)
// {
// count_up_br += 1;
// }
if (count_up_br + count_up_br_m >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(1.5f, (f_BPM_br[4] - f_BPM_br[3]));
}
else if (count_up_br + count_up_br_m >= 2)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(1, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(0.2f, (f_BPM_br[4] - f_BPM_br[3]));
}
count_down_br = 0;
count_down_br_m = 0;
count_out_range_br = 0;
}
else if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) <= ((-6) || f_BPM_br[4] - f_BPM_br[3] <= (-3))) // 较小值判断
{
// if (i_nodata_br == 0)
// {
// count_down_br += 1;
// }
if (count_down_br + count_down_br_m >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-1.5f), (f_BPM_br[4] - f_BPM_br[3]));
}
else if (count_down_br + count_down_br_m >= 2)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-1), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-0.2f), (f_BPM_br[4] - f_BPM_br[3]));
}
count_up_br = 0;
count_up_br_m = 0;
count_out_range_br = 0;
}
else if (f_BPM_br[4] - f_BPM_br[3] > 0)
{
// if (i_nodata_br == 0)
// {
// count_up_br_m += 1;
// }
if (count_up_br + count_up_br_m >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(2, (f_BPM_br[4] - f_BPM_br[3]));
}
else if (count_up_br + count_up_br_m >= 2)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(1, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(0.3f, (f_BPM_br[4] - f_BPM_br[3]));
}
count_down_br = 0;
count_down_br_m = 0;
count_out_range_br = 0;
}
else if (f_BPM_br[4] - f_BPM_br[3] < 0)
{
// if (i_nodata_br == 0)
// {
// count_down_br_m += 1;
// }
if (count_down_br + count_down_br_m >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-2), (f_BPM_br[4] - f_BPM_br[3]));
}
else if (count_down_br + count_down_br_m >= 2)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-1), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-0.3f), (f_BPM_br[4] - f_BPM_br[3]));
}
count_up_br = 0;
count_up_br_m = 0;
count_out_range_br = 0;
}
if (f_BPM_br[4] < 10)
{
f_BPM_br[4] = 10;
}
else if (f_BPM_br[4] > 25)
{
f_BPM_br[4] = 25;
}
BreathRate = round(f_BPM_br[4]);
// note: 增加对应的偏置
#if LINE_COEFF_EN
if (BreathRate >= 13 && BreathRate <= 30)
BreathRate = round((BreathRate - 13) * 0.2 + BreathRate);
#else
;
#endif
// printf("----------------------------Frq: %.6f\r\n", freq_calculated(nf, 1));
// printf("br-i_max: %d %d %.6f\r\n", i_max_br, BreathRate, freq_calculated(nf, 1));
}
else
{
int Count = 0;
float sum, avg = 0.0f;
for (char i = 0; i < 5; i++)
{
// printf("f_BPM_hr[%d] = %f\r\n", i, f_BPM_hr[i]);
if ((f_BPM_br[i]) != 0)
{
// printf("Rand Data :%d\r\n", (rand() % (5)));
sum += (f_BPM_br[i]);
Count++;
}
}
avg = sum / Count;
BreathRate = (uint8_t)(round(avg));
if (BreathRate < 10)
{
BreathRate = 10;
}
else if (BreathRate > 25)
{
BreathRate = 25;
}
}
}
/**
* @function:cwt_getBreath_Test
* @brief 测试通过滤波数据出呼吸
* @return {*}
* @author: lzc
*/
void cwt_getBreath_Test(void)
{
int n = 400; // 每次计算数据长度为4008s
int size = 0;
int i_max_br = 0; // 幅值最大值所在行(对应心率频率)
float max_sum = 0.0f; // 求最大幅值
float sum_amp_br[12] = {0.0f}; // 心率幅值求和
memset(amp, 0, sizeof(float) * 45 * 400);
// 拼数组
printf("Start!!!\r\n");
size = sizeof(cwtBreathBuffer) / sizeof(float);
printf("size is %d\r\n", size);
for (char i = 0; i < 2 * (size / n); i++)
{
memcpy(BreathDataArray, cwtBreathBuffer + (200 * i), sizeof(float) * 400);
cwt_rr((float *)BreathDataArray, n, amp); // 心率小波转换
for (int i = 0; i < 12; i++) // 对每行幅值数据求和
sum_amp_br[i] = MyToolSumValue(amp[i], n);
i_max_br = MyToolFindMaxIndex(sum_amp_br, 12);
max_sum = sum_amp_br[i_max_br];
breathDataPostProcessing();
printf("!!!!! BreathRate Date %d !!!!!!\r\n", BreathRate);
}
memset(BreathDataArray, 0, sizeof(BreathDataArray));
memset(f_BPM_br2, 0, sizeof(f_BPM_br2));
memset(f_BPM_br, 0, sizeof(f_BPM_br));
printf("End!!!\r\n");
}
#include "MyBandFitter.h"
void apply_hanning_window(float32_t *input, float32_t *output, uint32_t data_len, uint32_t FFT_SIZE)
{
// 生成汉宁窗系数并加窗
for (uint32_t i = 0; i < data_len; i++)
{
float32_t window = 0.5f * (1 - cosf(2 * PI * i / (data_len - 1)));
output[i] = input[i] * window;
}
// 补零至FFT_SIZE
memset(&output[data_len], 0, (FFT_SIZE - data_len) * sizeof(float32_t));
}
/**
* @function: fft_Output
* @brief: None
* @param {float32_t} *Input
* @return {*}
* @author: lzc
*/
#define FFT_POINT 2048
uint32_t FFT_Size = FFT_POINT;
float32_t FFT_InPut[FFT_POINT] = {0};
float32_t FFT_OutPut[(FFT_POINT / 2) + 1] = {0};
float32_t FFT_OutPut_Real[FFT_POINT] = {0};
float stash_Ratio[ARRAY_NUMBER] = {0};
uint16_t fft_HeartBeatCurrentFilter = 0;
float32_t HeartValueRes2Peaks[4] = {0.0f};
float32_t FFT_HeartRateRes[2] = {0.0f};
float32_t Energy_Ratio[4] = {0.0f};
float32_t fft_Output(float32_t *Input, int Length, char type)
{
float32_t FFT_HeartRateVal[2] = {0};
memset(FFT_OutPut_Real, 0, sizeof(FFT_OutPut_Real));
memset(FFT_OutPut, 0, sizeof(FFT_OutPut));
memset(FFT_InPut, 0, sizeof(FFT_InPut));
//-----------------------FFT--------------------------------------
// arm_float_to_q15(testInput_float_50hz, testInput_q15_50hz, FFT_Size);
uint32_t FFT_Dir = 0;
uint32_t doBitReverse = 1;
uint32_t Freq_Index = 0;
float32_t res = 0;
float32_t Freq = 0;
// FFT初始化
arm_rfft_fast_instance_f32 FFT_Struct;
// printf("\r\n-----------------Start---------------------\n");
/* 初始化结构体S*/
arm_rfft_fast_init_f32(&FFT_Struct, FFT_Size);
apply_hanning_window(Input, FFT_InPut, Length, FFT_Size); // 加hanning窗且补零到2048
arm_rfft_fast_f32(&FFT_Struct, FFT_InPut, FFT_OutPut_Real, FFT_Dir);
/* 实数FFT运算*/
arm_cmplx_mag_f32(FFT_OutPut_Real, FFT_OutPut, (FFT_POINT / 2) + 1);
// 能量修正乘以1.63
float32_t total_energy = 0.0f;
for (int i = 0; i < (FFT_Size / 2) + 1; i++)
{
FFT_OutPut[i] *= 1.63f; // 能量校准
total_energy += (FFT_OutPut[i]) * (FFT_OutPut[i]);
}
#if 0
if (type == TYPE_HEART)
{
Freq_Index = MyToolFindMaxIndex(FFT_OutPut, (FFT_POINT / 2));
Freq = ((float32_t)Freq_Index * 50.0f) / FFT_POINT;
res = (Freq * 60);
return res;
}
#else
if (type == TYPE_HEART)
{
int valuePeakNum = 0; // 最大的两个有效峰值数 0-2之间
int maxPeakIndex[2] = {0, 0}; // 用于最有可能的2个索引最后的结果放在这
float maxPeakValue[2] = {0.0f}; // 用于存放最大的2个峰值最后的结果放在这
valuePeakNum = peakProcess(FFT_OutPut, 200, maxPeakIndex, maxPeakValue);
// 对不一样滤波器 进行计算
if (fft_HeartBeatCurrentFilter == FILTER_HI_TYPE)
{
stash_Ratio[0] = maxPeakValue[1] / maxPeakValue[0];
Energy_Ratio[0] = (maxPeakValue[0] * maxPeakValue[0]) / total_energy;
Energy_Ratio[1] = (maxPeakValue[1] * maxPeakValue[1]) / total_energy;
}
else if (fft_HeartBeatCurrentFilter == FILTER_LO_TYPE)
{
stash_Ratio[1] = maxPeakValue[1] / maxPeakValue[0];
Energy_Ratio[2] = (maxPeakValue[0] * maxPeakValue[0]) / total_energy;
Energy_Ratio[3] = (maxPeakValue[1] * maxPeakValue[1]) / total_energy;
}
FFT_HeartRateVal[0] = (((float32_t)maxPeakIndex[0] * 50.0f) / FFT_POINT) * 60;
FFT_HeartRateVal[1] = (((float32_t)maxPeakIndex[1] * 50.0f) / FFT_POINT) * 60;
printf("FFT_HeartRateVal [0] : %f", FFT_HeartRateVal[0]);
printf("FFT_HeartRateVal [1] : %f", FFT_HeartRateVal[1]);
memcpy(FFT_HeartRateRes, FFT_HeartRateVal, sizeof(FFT_HeartRateVal));
return 0;
}
#endif
if (type == TYPE_BREATH)
{
// valuePeakNum = peakProcess(FFT_OutPut_Accumulate, 33, maxPeakIndex, maxPeakValue);
Freq_Index = MyToolFindMaxIndex(FFT_OutPut, 33);
Freq = ((float32_t)Freq_Index * 50.0f) / FFT_POINT;
res = (Freq * 60);
return res;
}
return 1;
//----------------------------------------------------------------
}
/**
* @function:heartDataPostProcessing
* @brief 心率数据后处理
* @return {*}
* @author: lzc
*/
void fft_heartDataPostProcessing(float32_t data)
{
move_update(f_BPM_hr, 5, (data));
f_BPM_hr[4] -= (f_BPM_hr[4] <= 90) ? 3 : 4; // 固定offset
// note: 增加对应的偏置
#if LINE_COEFF_EN
if (HeartBeatRate >= 83 && HeartBeatRate <= 110)
HeartBeatRate = round((HeartBeatRate - 83) * 0.23 + 3 + HeartBeatRate);
#else
;
#endif
//========================================================================数据后处理
memcpy(f_BPM_hr2, f_BPM_hr, sizeof(float) * 4);
if (f_BPM_hr[0] > 0) // 当数据满5个之后开始后处理
{
if ((f_BPM_hr[4] - MyToolMidValue(f_BPM_hr2, 4) >= 10) || (f_BPM_hr[4] - f_BPM_hr[3] >= 5)) // 比前4个中位数大12或比前面一个大8????????????????????????????????????????????
{
count_up_hr += 1; // 判断上升的条件+1,苛刻
#if FFT_VERSION
if (count_up_hr >= 12)
#else
if (count_up_hr >= 8)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + (3 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 3 : (f_BPM_hr[4] - f_BPM_hr[3])); // 最多+3
}
#if FFT_VERSION
else if (count_up_hr >= 6)
#else
else if (count_up_hr >= 4)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + (2 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 2 : (f_BPM_hr[4] - f_BPM_hr[3])); // 最多+2
}
else
{
f_BPM_hr[4] = f_BPM_hr[3] + 1;
}
count_down_hr = 0;
count_down_hr_m = 0;
count_out_range_hr = 0;
}
else if ((f_BPM_hr[4] - MyToolMidValue(f_BPM_hr2, 4) <= (-8)) || (f_BPM_hr[4] - f_BPM_hr[3] <= (-6))) // 比前4个中位数小8或比前面一个值小6
{
count_down_hr += 1;
#if FFT_VERSION
if (count_down_hr >= 6)
#else
if (count_down_hr >= 4)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-2) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-2) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
#if FFT_VERSION
else if (count_down_hr >= 3)
#else
else if (count_down_hr >= 2)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-1) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-1) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
else
{
f_BPM_hr[4] = f_BPM_hr[3];
}
count_up_hr = 0;
count_up_hr_m = 0;
count_out_range_hr = 0;
}
else if (f_BPM_hr[4] - f_BPM_hr[3] > 0)
{
if (f_BPM_hr[4] - f_BPM_hr[3] >= 3)
{
count_up_hr_m += 1;
#if FFT_VERSION
if (count_up_hr + count_up_hr_m >= 10)
#else
if (count_up_hr + count_up_hr_m >= 8)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + (2 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 2 : (f_BPM_hr[4] - f_BPM_hr[3])); // 最多+2
}
#if FFT_VERSION
else if (count_up_hr_m >= 8)
#else
else if (count_up_hr_m >= 8)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + (2 < (f_BPM_hr[4] - f_BPM_hr[3]) ? 2 : (f_BPM_hr[4] - f_BPM_hr[3])); // 最多+2
}
#if FFT_VERSION
else if (count_up_hr_m >= 2)
#else
else if (count_up_hr_m >= 2)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + 1;
}
else
{
f_BPM_hr[4] = f_BPM_hr[3];
}
}
count_down_hr = 0;
count_down_hr_m = 0;
count_out_range_hr = 0;
// count_up_hr = 0;
}
else if (f_BPM_hr[4] - f_BPM_hr[3] < 0)
{
if (f_BPM_hr[4] - f_BPM_hr[3] <= (-3))
{
count_down_hr_m += 1;
#if FFT_VERSION
if (count_down_hr + count_down_hr_m >= 8)
#else
if (count_down_hr + count_down_hr_m >= 8)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-2) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-2) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
#if FFT_VERSION
else if (count_down_hr_m >= 6)
#else
else if (count_down_hr_m >= 4)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + ((-2) > (f_BPM_hr[4] - f_BPM_hr[3]) ? (-2) : (f_BPM_hr[4] - f_BPM_hr[3]));
}
#if FFT_VERSION
else if (count_down_hr_m >= 2)
#else
else if (count_down_hr_m >= 2)
#endif
{
f_BPM_hr[4] = f_BPM_hr[3] + (-1);
}
else
{
f_BPM_hr[4] = f_BPM_hr[3];
}
}
count_up_hr = 0;
count_up_hr_m = 0;
count_out_range_hr = 0;
}
if (f_BPM_hr[4] <= 40)
{
f_BPM_hr[4] = 40;
}
else if (f_BPM_hr[4] > 170)
{
f_BPM_hr[4] = 170;
}
/**/
HeartBeatRate = (uint8_t)round(f_BPM_hr[4]);
// rt_kprintf("------------------- Freq %.6f\r\n", freq_calculated(nf, 0));
}
else // 数据没满五个,取平均值, 且输出值固定在65-75之间
{
int Count = 0;
float sum = 0.0f, avg = 0.0f;
for (char i = 0; i < 5; i++)
{
// rt_kprintf("f_BPM_hr[%d] = %f\r\n", i, f_BPM_hr[i]);
if ((f_BPM_hr[i]) != 0)
{
// rt_kprintf("Rand Data :%d\r\n", (rand() % (5)));
sum += (f_BPM_hr[i]);
Count++;
}
}
avg = sum / Count;
HeartBeatRate = (uint8_t)((round(avg)));
if (HeartBeatRate <= 65)
{
HeartBeatRate = 65;
}
else if (HeartBeatRate > 75)
{
HeartBeatRate = 75;
}
}
}
/**
* @function:breathDataPostProcessing
* @brief 呼吸数据后处理
* @return {*}
* @author: lzc
*/
static int hi_counter = 0;
static int lo_counter = 0;
void fft_breathDataPostProcessing(float32_t data)
{
int temp = round(data);
if (temp > 9)
lo_counter = 0;
if (temp < 24)
hi_counter = 0;
if (temp <= 9)
{
lo_counter++;
if (lo_counter <= 40)
temp = 14;
if (lo_counter >= 50)
lo_counter = 50;
}
else if (temp >= 24)
{
hi_counter++;
if (hi_counter <= 40)
temp = 15;
if (hi_counter >= 50)
hi_counter = 50;
}
move_update(f_BPM_br, 5, temp);
// note: 增加对应的偏置
if (f_BPM_br[4] < 10)
f_BPM_br[4] = f_BPM_br[4];
else
f_BPM_br[4] = f_BPM_br[4] - 0;
//========================================================================数据后处理
// if (f_BPM_br[0] > 0 && f_BPM_br2[0] == 0) // 保证最开始的前2个数据可靠性
// {
// if (fabs(f_BPM_br[0] - MyToolMidValue(f_BPM_br, 5)) > 0.1f)
// {
// f_BPM_br[0] = MyToolMidValue(f_BPM_br, 5);
// }
// if (fabs(f_BPM_br[1] - MyToolMidValue(f_BPM_br, 5)) > 0.1f)
// {
// f_BPM_br[1] = MyToolMidValue(f_BPM_br, 5);
// }
// }
for (int i = 0; i < 4; i++) // 把前4个数据复制出来供后处理分析
{
f_BPM_br2[i] = f_BPM_br[i];
}
if (f_BPM_br[0] > 0) // 当数据满5个之后开始后处理
{
/*
if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) >= (3) ||
f_BPM_br[4] - f_BPM_br[3] >= 2) // 比前4个中位数大3
{
count_out_range_br += 1;
if (count_out_range_br > 1)
{
count_down_br = 0;
count_down_br_m = 0;
count_up_br = 0;
count_up_br_m = 0;
}
if (count_out_range_br >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(3, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3];
}
}
else if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) <= (-10) ||
f_BPM_br[4] - f_BPM_br[3] <= (-8)) // 比前4个中位数小8
{
count_out_range_br += 1;
if (count_out_range_br > 1)
{
count_down_br = 0;
count_down_br_m = 0;
count_up_br = 0;
count_up_br_m = 0;
}
if (count_out_range_br >= 3)
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-3), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3];
}
}
*/
// else
if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) >= (3) ||
f_BPM_br[4] - f_BPM_br[3] >= 2) // 较大值判断
{
count_up_br++;
#if FFT_VERSION
if (count_up_br >= 10)
#else
if (count_up_br >= 8)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(2.0f, (f_BPM_br[4] - f_BPM_br[3]));
}
#if FFT_VERSION
else if (count_up_br >= 6)
#else
else if (count_up_br >= 4)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(1.0f, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3]; // min_compare(0.2f, (f_BPM_br[4] - f_BPM_br[3]));
}
count_down_br = 0;
count_down_br_m = 0;
count_out_range_br = 0;
}
else if (f_BPM_br[4] - MyToolMidValue(f_BPM_br2, 4) <= ((-3) || f_BPM_br[4] - f_BPM_br[3] <= (-2))) // 较小值判断
{
count_down_br++;
#if FFT_VERSION
if (count_down_br >= 10)
#else
if (count_down_br >= 8)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-2.0f), (f_BPM_br[4] - f_BPM_br[3]));
}
#if FFT_VERSION
else if (count_down_br >= 6)
#else
else if (count_down_br >= 4)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-1), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3]; // + max_compare((-0.2f), (f_BPM_br[4] - f_BPM_br[3]));
}
count_up_br = 0;
count_up_br_m = 0;
count_out_range_br = 0;
}
else if (f_BPM_br[4] - f_BPM_br[3] > 0)
{
count_up_br_m++;
#if FFT_VERSION
if (count_up_br_m >= 3)
#else
if (count_up_br_m >= 3)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + min_compare(1, (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3]; // + min_compare(0.3f, (f_BPM_br[4] - f_BPM_br[3]));
}
count_down_br = 0;
count_down_br_m = 0;
count_out_range_br = 0;
count_up_br = 0;
}
else if (f_BPM_br[4] - f_BPM_br[3] < 0)
{
count_down_br_m++;
#if FFT_VERSION
if (count_down_br_m >= 3)
#else
if (count_down_br_m >= 3)
#endif
{
f_BPM_br[4] = f_BPM_br[3] + max_compare((-1), (f_BPM_br[4] - f_BPM_br[3]));
}
else
{
f_BPM_br[4] = f_BPM_br[3]; // + max_compare((-0.3f), (f_BPM_br[4] - f_BPM_br[3]));
}
count_up_br = 0;
count_up_br_m = 0;
count_out_range_br = 0;
count_down_br = 0;
}
if (f_BPM_br[4] < 7)
{
f_BPM_br[4] = 7;
}
else if (f_BPM_br[4] > 35)
{
f_BPM_br[4] = 35;
}
/**/
BreathRate = round(f_BPM_br[4]);
// rt_kprintf("----------------------------Frq: %.6f\r\n", freq_calculated(nf, 1));
// rt_kprintf("br-i_max: %d %d %.6f\r\n", i_max_br, BreathRate, freq_calculated(nf, 1));
}
else
{
int Count = 0;
float sum, avg = 0.0f;
for (char i = 0; i < 5; i++)
{
// rt_kprintf("f_BPM_hr[%d] = %f\r\n", i, f_BPM_hr[i]);
if ((f_BPM_br[i]) != 0)
{
// rt_kprintf("Rand Data :%d\r\n", (rand() % (5)));
sum += (f_BPM_br[i]);
Count++;
}
}
avg = sum / Count;
BreathRate = (uint8_t)(round(avg));
if (BreathRate < 11)
{
BreathRate = 11;
}
else if (BreathRate > 15)
{
BreathRate = 15;
}
}
}
//------------------------------------------------------------------------------//
//----------------------------------FFT-----------------------------------------//
//---------------------------Cooley-Tukey算法-----------------------------------//
//------------------------------------------------------------------------------//
struct complex
{
double real;
double image;
};
struct complex complex_add(struct complex c1, struct complex c2);
struct complex complex_sub(struct complex c1, struct complex c2);
struct complex complex_multi(struct complex c1, struct complex c2);
struct complex rotation_factor(int N, int n, int k);
double mold_length(struct complex c);
// void fft(int len, struct complex in_x[],struct complex out_y[]);
void fft(int len, int len_array, struct complex in_x[], float out_y[len_array]);
#define N 2048
#define N1 600
struct complex
complex_add(struct complex c1, struct complex c2) // 复数加法
{
struct complex p;
p.real = c1.real + c2.real;
p.image = c1.image + c2.image;
return p;
}
struct complex complex_sub(struct complex c1, struct complex c2) // 复数减
{
struct complex p;
p.real = c1.real - c2.real;
p.image = c1.image - c2.image;
return p;
}
struct complex complex_multi(struct complex c1, struct complex c2) // 复数乘法
{
struct complex c3;
c3.real = c1.real * c2.real - c1.image * c2.image;
c3.image = c2.real * c1.image + c1.real * c2.image;
return c3;
}
struct complex rotation_factor(int Length, int n, int k) // 旋转因子
{
struct complex w;
w.real = cos(2 * PI * n * k / Length);
w.image = -sin(2 * PI * n * k / Length);
return w;
}
double mold_length(struct complex c) // 幅度
{
return sqrt(c.real * c.real + c.image * c.image);
};
int reverse_num(int l, int oringin_num) // 反位序
{
int q = 0, m = 0;
for (int k = l - 1; k >= 0; k--)
{
q = oringin_num % 2;
m += q * (1 << k);
oringin_num = oringin_num / 2;
}
return m;
}
/**
* @function: cooley_tukey_fft
* @brief: FFT 计算
* @param {int} len 计算长度
* @param {int} len_array 数据长度
* @param {complex} in_x 输入数据
* @param {float} out_y 输出数据
* @return {*}
* @author: lzc
*/
void cooley_tukey_fft(int len, int len_array, struct complex in_x[], float out_y[(len / 2)])
{
/*
param len 序列长度目前只能是2的指数
param in_x输入的序列
param out_y输出的序列
*/
int l, k, r, z, dist, q, j; // l是级
struct complex w, tmp;
struct complex in_x_mem[len];
l = log2(len);
for (k = 0; k < len; k++)
{
in_x_mem[k] = in_x[reverse_num(l, k)]; // 反位序号操作
}
for (r = 0; r < l; r++) // 遍历每一级蝶形运算
{
dist = 1 << r; // 提前计算每一级的间隔距离
for (j = 0; j < dist; j++) // 计算策略是拆成上下两组先上计算后下计算j是计算的起始序号
{
for (k = j; k < len; k += (dist << 1)) // 不好解释,得画图理解
{
q = k + dist; // q同一组蝶形运算第二个序号
z = k << (l - r - 1); // 确定旋转因子的指数
w = rotation_factor(len, 1, z);
// 由于不是并行计算,必须先缓存
tmp = in_x_mem[k];
in_x_mem[k] = complex_add(in_x_mem[k], complex_multi(w, in_x_mem[q]));
in_x_mem[q] = complex_sub(tmp, complex_multi(w, in_x_mem[q]));
}
}
}
for (int ii = 0; ii < (len * 0.5); ii++)
{
out_y[ii] = mold_length(in_x_mem[ii]);
}
// memcpy(out_y,in_x_mem,len*sizeof(struct complex));
}
/**
* @function: myFFT_Output
* @brief: None
* @param {float32_t} *Input
* @param {int} Length
* @param {char} type
* @return {*}
* @author: lzc
*/
float32_t myFFT_Output(float32_t *Input, int Length, char type)
{
float32_t res = 0;
float32_t Freq = 0;
// float32_t y[N1] = {0};
float32_t *y = malloc(sizeof(float32_t) * 1024);
uint32_t Freq_Index = 0;
struct complex x[N] = {0}; // 初始化为0
// printf("\n==========Start================\n");
for (int i = 0; i < N; i++)
{
if (i >= 0 && i < Length)
{
x[i].real = Input[i];
x[i].image = 0;
}
else
{
x[i].real = 0;
x[i].image = 0;
}
}
cooley_tukey_fft(N, Length, x, y);
// for (int i = 0; i < N / 2; i++)
// printf("%f\r\n", y[i]);
if (type == TYPE_HEART)
Freq_Index = MyToolFindMaxIndex(y, (FFT_POINT / 2));
else if (type == TYPE_BREATH)
Freq_Index = MyToolFindMaxIndex(y, 33);
Freq = ((float32_t)Freq_Index * 50.0f) / FFT_POINT;
res = (Freq * 60);
free(y);
// printf("\n==========End================\n");
return res;
}