| 1634 | } |
| 1635 | |
| 1636 | int get_heart_rate ( |
| 1637 | double *ppg_ir, double *ppg_red, int data_size, int sampling_rate, int fft_size, double *rate) |
| 1638 | { |
| 1639 | if ((ppg_red == NULL) || (ppg_ir == NULL) || (data_size < fft_size) || (sampling_rate < 1) || |
| 1640 | (rate == NULL) || (fft_size < 1024) || (fft_size % 2 != 0)) |
| 1641 | { |
| 1642 | data_logger->error ( |
| 1643 | "invalid inputs for get_heart_rate, fft_len should be even and at least 1024"); |
| 1644 | return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; |
| 1645 | } |
| 1646 | |
| 1647 | int psd_size = fft_size / 2 + 1; |
| 1648 | double *output_ampl_ir = new double[psd_size]; |
| 1649 | double *output_ampl_red = new double[psd_size]; |
| 1650 | double *output_freq = new double[psd_size]; |
| 1651 | |
| 1652 | int res = get_psd_welch (ppg_ir, data_size, fft_size, fft_size / 2, sampling_rate, |
| 1653 | (int)WindowOperations::HANNING, output_ampl_ir, output_freq); |
| 1654 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1655 | { |
| 1656 | res = get_psd_welch (ppg_red, data_size, fft_size, fft_size / 2, sampling_rate, |
| 1657 | (int)WindowOperations::HANNING, output_ampl_red, output_freq); |
| 1658 | } |
| 1659 | if (res == (int)BrainFlowExitCodes::STATUS_OK) |
| 1660 | { |
| 1661 | // calc HR using red/ir psd. HR range 35bpm-230bpm |
| 1662 | // average ampls for red and ir, store in red |
| 1663 | for (int i = 0; i < psd_size; i++) |
| 1664 | { |
| 1665 | output_ampl_red[i] = (output_ampl_red[i] + output_ampl_ir[i]) / 2; |
| 1666 | } |
| 1667 | double min_hr = 35.0 / 60.0; |
| 1668 | double max_hr = 230.0 / 60.0; |
| 1669 | // find max amplitude |
| 1670 | double max_ampl = 0.0; |
| 1671 | int max_ampl_index = 0; |
| 1672 | for (int i = 0; i < psd_size; i++) |
| 1673 | { |
| 1674 | if (output_freq[i] > min_hr && output_freq[i] < max_hr && output_ampl_red[i] > max_ampl) |
| 1675 | { |
| 1676 | max_ampl = output_ampl_red[i]; |
| 1677 | max_ampl_index = i; |
| 1678 | } |
| 1679 | else if (output_freq[i] > max_hr) |
| 1680 | { |
| 1681 | break; |
| 1682 | } |
| 1683 | } |
| 1684 | double heart_rate = output_freq[max_ampl_index] * 60; |
| 1685 | *rate = heart_rate; |
| 1686 | } |
| 1687 | |
| 1688 | delete[] output_ampl_ir; |
| 1689 | delete[] output_ampl_red; |
| 1690 | delete[] output_freq; |
| 1691 | |
| 1692 | return res; |
| 1693 | } |
no test coverage detected