18 #define DOUBLE_BUFFERING_MEAN_ABS_DEV_OUTLIER_TH 5
46 static void rfft(
const float *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride);
48 static void fftshift(
float *data, uint16_t data_length, uint16_t stride);
50 static void welch(
const float complex *data,
52 uint16_t segment_length,
53 float complex *data_buffer,
54 float complex *fft_out,
57 uint16_t length_shift,
61 static void filter_inplace_apply(uint16_t sample_idx,
const float *b,
const float *a,
float state[5],
float *data);
67 static void small_rfft(
const float *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride);
69 static void small_fft(
const float complex *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride);
75 static void sort_i16(int16_t *array, uint16_t array_length);
77 static void swap_i16(int16_t *array, uint16_t idx_a, uint16_t idx_b);
79 static void sort_f32(
float *array, uint16_t array_length);
81 static void swap_f32(
float *array, uint16_t idx_a, uint16_t idx_b);
96 const uint16_t sweeps_per_frame,
97 const uint16_t num_points,
99 const uint16_t point);
113 const uint16_t num_points,
114 const uint16_t sweep,
115 const uint16_t point,
116 const uint16_t median_start_sweep);
132 const float *velocities,
133 const float *energies,
134 const uint16_t *peak_idxs,
135 float *merged_velocities,
136 float *merged_energies,
137 uint16_t cluster_count);
161 for (uint16_t i = 1U; i < data_length; i++)
163 data[i - 1U] = data[i];
166 data[data_length - 1U] = element;
173 for (uint16_t r = rows - 1U; r > 0U; r--)
175 for (uint16_t c = 0U; c < cols; c++)
177 data[(r * cols) + c] = data[((r - 1U) * cols) + c];
181 for (uint16_t c = 0U; c < cols; c++)
188 for (uint16_t r = 1U; r < rows; r++)
190 for (uint16_t c = 0U; c < cols; c++)
192 data[((r - 1U) * cols) + c] = data[(r * cols) + c];
196 for (uint16_t c = 0U; c < cols; c++)
198 data[((rows - 1U) * cols) + c] = column[c];
207 for (uint16_t r = rows - 1U; r > 0U; r--)
209 for (uint16_t c = 0U; c < cols; c++)
211 data[(r * cols) + c] = data[((r - 1U) * cols) + c];
215 for (uint16_t c = 0U; c < cols; c++)
222 for (uint16_t r = 1U; r < rows; r++)
224 for (uint16_t c = 0U; c < cols; c++)
226 data[((r - 1U) * cols) + c] = data[(r * cols) + c];
230 for (uint16_t c = 0U; c < cols; c++)
232 data[((rows - 1U) * cols) + c] = column[c];
241 uint16_t matrix_rows,
244 for (uint16_t m_rows = 0U; m_rows < matrix_rows; m_rows++)
248 for (uint16_t r = data_rows - 1U; r > 0U; r--)
250 for (uint16_t c = 0U; c < cols; c++)
252 data[(r * cols) + c].real = data[((r - 1U) * cols) + c].real;
253 data[(r * cols) + c].imag = data[((r - 1U) * cols) + c].imag;
257 for (uint16_t c = 0U; c < cols; c++)
259 data[c].
real = matrix[(m_rows * cols) + c].real;
260 data[c].
imag = matrix[(m_rows * cols) + c].imag;
265 for (uint16_t r = 1U; r < data_rows; r++)
267 for (uint16_t c = 0U; c < cols; c++)
269 data[((r - 1U) * cols) + c].
real = data[(r * cols) + c].real;
270 data[((r - 1U) * cols) + c].
imag = data[(r * cols) + c].imag;
274 for (uint16_t c = 0U; c < cols; c++)
276 data[((data_rows - 1U) * cols) + c].
real = matrix[(m_rows * cols) + c].real;
277 data[((data_rows - 1U) * cols) + c].
imag = matrix[(m_rows * cols) + c].imag;
285 for (uint16_t i = 1U; i < data_length; i++)
287 float diff = data[i] - data[i - 1U];
289 while ((diff > (
float)
M_PI) || (diff < -(
float)
M_PI))
291 if (diff > (
float)
M_PI)
293 data[i] -= 2.0f * (float)
M_PI;
297 data[i] += 2.0f * (float)
M_PI;
300 diff = data[i] - data[i - 1U];
308 float max = data[idx];
310 for (uint16_t i = 1U; i < data_length; i++)
324 float a = ((x[0] * (y[2] - y[1])) + (x[1] * (y[0] - y[2])) + (x[2] * (y[1] - y[0]))) / ((x[0] - x[1]) * (x[0] - x[2]) * (x[1] - x[2]));
325 float b = ((y[1] - y[0]) / (x[1] - x[0])) - (a * (x[0] + x[1]));
327 return -b / (2.0f * a);
332 float peak_offset = (y[peak_idx - 1U] - y[peak_idx + 1U]) / ((2.0f * y[peak_idx - 1U]) - (4.0f * y[peak_idx]) + (2.0f * y[peak_idx + 1U]));
334 return x_start + (((float)peak_idx + peak_offset) * x_delta);
339 float factor = (2.0f * freq) / fs;
344 p[0] = -cexpf(((-1.0f * (
float)
M_PI) / 4.0f) * I);
345 p[1] = -cexpf(((1.0f * (
float)
M_PI) / 4.0f) * I);
348 factor = 4.0f * tanf(((
float)
M_PI * factor) / 2.0f);
351 p[0] = (
float complex)factor * p[0];
352 p[1] = (
float complex)factor * p[1];
355 float k = factor * factor;
358 float complex real_four = (
float complex)4.0f;
359 float complex z_prod = 1.0f;
360 float complex p_prod = (real_four - p[0]) * (real_four - p[1]);
369 float z_z[2] = {-1.0f, -1.0f};
372 a[0] = -(p[0] + p[1]);
375 b[1] = -k * (z_z[0] + z_z[1]);
376 b[2] = k * (z_z[0] * z_z[1]);
381 float min_f = (2.0f * min_freq) / fs;
382 float max_f = (2.0f * max_freq) / fs;
387 p[0] = -cexpf(((-1.0f * (
float)
M_PI) / 4.0f) * I);
388 p[1] = -cexpf(((1.0f * (
float)
M_PI) / 4.0f) * I);
392 min_f = 4.0f * tanf(((
float)
M_PI * min_f) / 2.0f);
393 max_f = 4.0f * tanf(((
float)
M_PI * max_f) / 2.0f);
396 float bw = max_f - min_f;
397 float complex w0 = (
float complex)sqrtf(min_f * max_f);
400 float complex scale = (
float complex)(bw / 2.0f);
406 float complex p_bp[4];
409 p_bp[0] = p[0] + csqrtf((p[0] * p[0]) - w0);
410 p_bp[1] = p[1] + csqrtf((p[1] * p[1]) - w0);
411 p_bp[2] = p[0] - csqrtf((p[0] * p[0]) - w0);
412 p_bp[3] = p[1] - csqrtf((p[1] * p[1]) - w0);
415 float k_bp = k * bw * bw;
418 float complex real_four = (
float complex)4.0f;
419 float complex p_z[4];
427 float z_z[4] = {1.0f, 1.0f, -1.0f, -1.0f};
430 float complex z_prod = 16.0f;
431 float complex p_prod = (real_four - p_bp[0]) * (real_four - p_bp[1]) * (real_four - p_bp[2]) * (real_four - p_bp[3]);
435 a[0] = -(p_z[0] + p_z[1] + p_z[2] + p_z[3]);
436 a[1] = (p_z[0] * p_z[1]) + (p_z[0] * p_z[2]) + (p_z[0] * p_z[3]) + (p_z[1] * p_z[2]) + (p_z[1] * p_z[3]) + (p_z[2] * p_z[3]);
437 a[2] = -((p_z[0] * p_z[1] * p_z[2]) + (p_z[0] * p_z[1] * p_z[3]) + (p_z[0] * p_z[2] * p_z[3]) + (p_z[1] * p_z[2] * p_z[3]));
438 a[3] = p_z[0] * p_z[1] * p_z[2] * p_z[3];
440 b[1] = -k_z * (z_z[0] + z_z[1] + z_z[2] + z_z[3]);
441 b[2] = k_z * ((z_z[0] * z_z[1]) + (z_z[0] * z_z[2]) + (z_z[0] * z_z[3]) + (z_z[1] * z_z[2]) + (z_z[1] * z_z[3]) + (z_z[2] * z_z[3]));
442 b[3] = -k_z * ((z_z[0] * z_z[1] * z_z[2]) + (z_z[0] * z_z[1] * z_z[3]) + (z_z[0] * z_z[2] * z_z[3]) + (z_z[1] * z_z[2] * z_z[3]));
443 b[4] = k_z * (z_z[0] * z_z[1] * z_z[2] * z_z[3]);
448 float filter_states[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
450 for (uint16_t i = 0U; i < data_length; i++)
458 for (uint16_t i = 0U; i < rows; i++)
465 const float *filt_data,
473 uint16_t output_length)
475 for (uint16_t i = 0U; i < output_length; i++)
479 for (uint16_t r = 0U; r < filt_rows; r++)
481 output[i] -= a[r] * filt_data[i + (r * filt_cols)];
484 for (uint16_t r = 0U; r < data_rows; r++)
486 output[i] += b[r] * data[i + (r * data_cols)];
492 const float complex *filt_data,
496 const float complex *data,
499 float complex *output,
500 uint16_t output_length)
502 for (uint16_t i = 0U; i < output_length; i++)
507 for (uint16_t r = 0U; r < filt_rows; r++)
509 real -= a[r] * crealf(filt_data[i + (r * filt_cols)]);
510 imag -= a[r] * cimagf(filt_data[i + (r * filt_cols)]);
513 for (uint16_t r = 0U; r < data_rows; r++)
515 real += b[r] * crealf(data[i + (r * data_cols)]);
516 imag += b[r] * cimagf(data[i + (r * data_cols)]);
519 output[i] = real + (imag * I);
525 uint16_t sweeps_per_frame,
526 uint16_t start_point,
528 float complex *sweep)
530 for (uint16_t n = start_point; n < end_point; n++)
532 mean_i16_complex(&frame[n], sweeps_per_frame, &sweep[n - start_point], num_points);
538 uint16_t sweeps_per_frame,
539 uint16_t start_point,
541 float complex *sum_sweep)
543 for (uint16_t n = start_point; n < end_point; n++)
545 sum_i16_complex(&frame[n], sweeps_per_frame, &sum_sweep[n - start_point], num_points);
558 for (uint16_t i = 0U; i < rows; i++)
565 for (uint16_t i = 0U; i < cols; i++)
578 for (uint16_t i = 0U; i < data_length; i++)
580 data[i] = conjf(data[i]);
586 for (uint16_t i = 0U; i < data_length; i++)
588 data[i] = data[i] / cabsf(data[i]);
592 void acc_algorithm_rfft(
const float *data, uint16_t data_length, uint16_t length_shift,
float complex *output)
594 rfft(data, data_length, length_shift, output, 1U);
597 void acc_algorithm_rfft_matrix(
const float *data, uint16_t rows, uint16_t cols, uint16_t length_shift,
float complex *output, uint16_t axis)
599 uint16_t full_cols = ((uint16_t)1U) << length_shift;
603 uint16_t output_cols = (full_cols / 2U) + 1U;
604 for (uint16_t i = 0U; i < rows; i++)
606 rfft(&data[i * cols], cols, length_shift, &output[i * output_cols], 1U);
611 for (uint16_t i = 0U; i < cols; i++)
613 rfft(&data[i], rows, length_shift, &output[i], cols);
622 void acc_algorithm_fft(
const float complex *data, uint16_t data_length, uint16_t length_shift,
float complex *output)
624 small_fft(data, data_length, length_shift, output, 1U);
627 void acc_algorithm_fft_matrix(
const float complex *data, uint16_t rows, uint16_t cols, uint16_t length_shift,
float complex *output, uint16_t axis)
629 uint16_t full_cols = ((uint16_t)1U) << length_shift;
633 uint16_t output_cols = full_cols;
634 for (uint16_t i = 0U; i < rows; i++)
636 small_fft(&data[i * cols], cols, length_shift, &output[i * output_cols], 1U);
641 for (uint16_t i = 0U; i < cols; i++)
643 small_fft(&data[i], rows, length_shift, &output[i], cols);
656 if ((n > 0U) && (d > 0.0f))
658 df = 1.0f / ((float)n * d);
666 uint16_t n_freqs = (n / 2U) + 1U;
669 for (uint16_t i = 0U; i < n_freqs; i++)
671 freqs[i] = (float)i * df;
678 uint16_t mid = n / 2U;
680 for (uint16_t i = 0U; i < mid; i++)
682 freqs[i] = (float)i * df;
685 int32_t n_int32 = (int32_t)n;
687 for (int32_t i = (int32_t)mid; i < n_int32; i++)
689 int32_t diff = i - n_int32;
690 freqs[i] = (float)diff * df;
698 if ((fs != 0.0f) && (tc != 0.0f))
700 float dt = 1.0f / fs;
702 res = expf(-dt / tc);
710 double a = (double)crealf(denom);
711 double b = (double)cimagf(denom);
712 double c = (double)crealf(num);
713 double d = (double)cimagf(num);
715 float real = (float)(((c * a) + (b * d)) / ((a * a) + (b * b)));
716 float imag = (float)(((a * d) - (c * b)) / ((a * a) + (b * b)));
718 return real + (imag * I);
723 const float a = 0.54f;
724 const float b = 0.46f;
725 const float factor = (2.0f * (float)
M_PI) / ((float)n - 1.0f);
727 for (uint16_t i = 0U; i < n; i++)
729 window[i] = a - (b * cosf((
float)i * factor));
735 const float a = 0.5f;
737 const float factor = (2.0f * (float)
M_PI) / (float)n;
739 for (uint16_t i = 0U; i < n; i++)
741 window[i] = a - (a * cosf((
float)i * factor));
775 const uint16_t sweeps_per_frame,
776 const uint16_t num_points,
777 int32_t *work_buffer)
779 int32_t first_diff_r[2U];
780 int32_t first_diff_i[2U];
782 if (sweeps_per_frame >= 32U)
784 for (uint16_t point = 0U; point < num_points; point++)
786 int32_t abs_mad_sum = 0;
788 for (uint16_t sweep = 0U; sweep < (sweeps_per_frame - 2U); sweep++)
791 for (uint16_t idx = 0U; idx < 2U; idx++)
793 uint16_t sweep_idx = (sweep + idx) * num_points;
794 uint16_t next_sweep_idx = (sweep + idx + 1U) * num_points;
795 int32_t diff1_r = frame[(next_sweep_idx + point)].real;
796 int32_t diff1_i = frame[(next_sweep_idx + point)].imag;
797 int32_t diff2_r = frame[(sweep_idx + point)].real;
798 int32_t diff2_i = frame[(sweep_idx + point)].imag;
799 first_diff_r[idx] = diff1_r - diff2_r;
800 first_diff_i[idx] = diff1_i - diff2_i;
804 int32_t second_diff_r = first_diff_r[1] - first_diff_r[0U];
805 int32_t second_diff_i = first_diff_i[1] - first_diff_i[0U];
808 int32_t abs_r = (second_diff_r < 0) ? -second_diff_r : second_diff_r;
809 int32_t abs_i = (second_diff_i < 0) ? -second_diff_i : second_diff_i;
811 work_buffer[sweep] = abs_r + abs_i;
814 abs_mad_sum += work_buffer[sweep];
818 int32_t nof_of_abs = (int32_t)sweeps_per_frame;
819 nof_of_abs = nof_of_abs - 2;
820 int32_t diff_mad = abs_mad_sum / nof_of_abs;
823 for (uint16_t sweep = 1U; sweep < (sweeps_per_frame - 1U); sweep++)
825 if (work_buffer[sweep - 1U] <= threshold)
835 else if (sweep == (sweeps_per_frame - 2U))
851 for (uint16_t i = 0U; i < cols; i++)
865 uint16_t segment_length,
866 float complex *data_buffer,
867 float complex *fft_out,
870 uint16_t length_shift,
873 for (uint16_t i = 0U; i < cols; i++)
875 welch(&(data[i]), rows, segment_length, data_buffer, fft_out, &(psds[i]), window, length_shift, fs, cols);
880 uint16_t data_length,
881 uint16_t segment_length,
882 float complex *data_buffer,
883 float complex *fft_out,
886 uint16_t length_shift,
889 welch(data, data_length, segment_length, data_buffer, fft_out, psd, window, length_shift, fs, 1U);
893 uint16_t data_length,
894 uint16_t window_length,
895 uint16_t half_guard_length,
899 const uint16_t start_idx = window_length + half_guard_length;
900 const uint16_t end_idx = data_length - start_idx;
901 float threshold = 0.0f;
903 if ((idx < start_idx) || (idx >= end_idx))
909 float samples_sum = 0.0f;
910 uint16_t sample_count = 0U;
911 uint16_t take_window_close_start = idx - half_guard_length - window_length;
912 uint16_t take_window_far_start = idx + half_guard_length + 1U;
914 for (uint16_t k = 0; k < window_length; k++)
916 samples_sum += data[take_window_close_start + k];
917 samples_sum += data[take_window_far_start + k];
921 threshold = (sample_count > 0U) ? (samples_sum / (
float)sample_count) : 0.0f;
922 threshold += sensitivity;
929 uint16_t data_length,
931 uint16_t window_length,
932 uint16_t half_guard_length,
936 uint16_t margin = window_length + half_guard_length;
937 uint16_t half_sweep_len_without_margin = (uint16_t)rint(((
double)data_length / 2.0) - (double)margin);
939 float min = INFINITY;
941 for (uint16_t i = 0U; i < data_length; i++)
943 min = fminf(data[i], min);
950 for (uint16_t j = 0U; j < window_length; j++)
956 if ((idx > margin) && (idx < middle_idx))
958 for (uint16_t j = 0U; j < window_length; j++)
960 sum += data[j + (idx - margin)];
964 if ((idx >= middle_idx) && (idx < (data_length - margin - 1U)))
966 for (uint16_t j = 0U; j < window_length; j++)
968 sum += data[data_length - half_sweep_len_without_margin - j + idx - middle_idx];
972 if (idx >= (data_length - margin - 1U))
974 for (uint16_t j = 0U; j < window_length; j++)
976 sum += data[data_length - j - 1U];
980 return ((sum / (
float)window_length) + min) / sensitivity;
985 float max = -INFINITY;
989 for (uint16_t i = 0U; i < rows; i++)
991 if ((i < (middle_idx + half_slow_zone)) && (i >= (middle_idx - half_slow_zone)))
996 for (uint16_t j = 0U; j < cols; j++)
998 if (data[(i * cols) + j] > max)
1000 max = data[(i * cols) + j];
1011 float slow_vs = 0.0f;
1012 float valid_vs = 0.0f;
1013 bool has_valid =
false;
1014 float biggest_energy_slow = -INFINITY;
1015 float biggest_energy_valid = -INFINITY;
1017 for (uint16_t i = 0U; i < num_peaks; i++)
1019 uint16_t idx = (peak_idxs != NULL) ? peak_idxs[i] : i;
1021 if (energies[idx] > biggest_energy_slow)
1023 if (fabsf(velocities[idx]) < limit)
1025 slow_vs = velocities[idx];
1026 biggest_energy_slow = energies[idx];
1030 if (energies[i] > biggest_energy_valid)
1032 if (fabsf(velocities[idx]) >= limit)
1034 valid_vs = velocities[idx];
1035 biggest_energy_valid = energies[idx];
1041 return has_valid ? valid_vs : slow_vs;
1045 const float *velocities,
1046 const float *energies,
1047 const uint16_t *peak_idxs,
1049 float *merged_velocities,
1050 float *merged_energies,
1051 uint16_t merged_peaks_length,
1052 uint16_t *num_merged_peaks)
1055 uint16_t cluster_count = 0U;
1056 uint16_t cluster_start_idx = 0U;
1060 for (uint16_t i = 0U; i < (num_peaks - 1U); i++)
1062 uint16_t current_idx = peak_idxs[i];
1063 uint16_t next_idx = peak_idxs[i + 1U];
1065 uint16_t num_peaks_in_cluster = i - cluster_start_idx + 1U;
1067 bool current_peak_is_in_cluster = (velocities[next_idx] - velocities[current_idx]) < max_peak_separation;
1069 if (current_peak_is_in_cluster)
1074 status = cluster_count < merged_peaks_length;
1079 cluster_start_idx, num_peaks_in_cluster, velocities, energies, peak_idxs, merged_velocities, merged_energies, cluster_count);
1088 cluster_start_idx = i + 1U;
1092 bool last_cluster_not_merged = cluster_start_idx < num_peaks;
1094 if (status && last_cluster_not_merged)
1096 status = cluster_count < merged_peaks_length;
1101 cluster_start_idx, num_peaks - cluster_start_idx, velocities, energies, peak_idxs, merged_velocities, merged_energies, cluster_count);
1112 *num_merged_peaks = cluster_count;
1120 uint16_t steps = (idx * step_length) + start_point;
1122 return (
float)steps * base_step_length_m;
1131 float MIN_DIST_M[5] = {-1.0f, 0.07f * 2.0f, 0.14f * 2.0f, 0.19f * 2.0f, 0.32f * 2.0f};
1135 if ((MIN_DIST_M[i - 1U] == -1.0f) || (MIN_DIST_M[i - 1U] <= ((float)start_point * base_step_length)))
1146 float breakpoint_p = (float)breakpoint;
1147 float breakpoint_m = breakpoint_p * base_step_length;
1179 const uint16_t data_length,
1180 const uint32_t *threshold_check,
1181 uint16_t *peak_idxs,
1182 uint16_t peak_idxs_length,
1183 uint16_t *num_peaks)
1185 bool success =
true;
1186 uint16_t found_peaks = 0U;
1189 while (i < data_length)
1207 if (abs_sweep[i - 1U] >= abs_sweep[i])
1223 uint16_t d_upper = i + 1U;
1224 bool upper_done =
false;
1228 if (d_upper >= (data_length - 1U))
1236 else if (abs_sweep[d_upper] > abs_sweep[i])
1242 else if (abs_sweep[d_upper] < abs_sweep[i])
1254 if (found_peaks < peak_idxs_length)
1256 peak_idxs[found_peaks] = i;
1276 *num_peaks = found_peaks;
1284 const float threshold,
1287 uint16_t threshold_check_length,
1292 for (uint16_t r = offset; r < (threshold_check_length + offset); r++)
1295 for (uint16_t c = 0U; c < cols; c++)
1297 if (matrix[c + (r * cols)] > threshold)
1304 else if (axis == 1U)
1306 for (uint16_t c = offset; c < (threshold_check_length + offset); c++)
1309 for (uint16_t r = 0U; r < rows; r++)
1311 if (matrix[c + (r * cols)] > threshold)
1330 if ((length % 2U) == 0U)
1332 result = (data[(length / 2U) - 1U] + data[length / 2U]) / 2;
1336 result = data[length / 2U];
1348 if ((length % 2U) == 0U)
1350 result = (data[(length / 2U) - 1U] + data[length / 2U]) / 2.0f;
1354 result = data[length / 2U];
1362 float max_value = 0.0f;
1364 for (uint16_t i = 0; i < length; i++)
1366 if (data[i] > max_value)
1368 max_value = data[i];
1377 float weight_sum = 0.0f;
1378 float weighted_data_sum = 0.0f;
1379 float weighted_mean = 0.0f;
1381 for (uint16_t i = 0; i < length; i++)
1383 weight_sum += weights[i];
1384 weighted_data_sum += weights[i] * data[i];
1387 if (weight_sum > 0.0f)
1389 weighted_mean = weighted_data_sum / weight_sum;
1393 weighted_mean = data[0];
1396 return weighted_mean;
1402 float sq_err_sum = 0.0f;
1403 float variance = 0.0f;
1407 for (uint16_t i = 0U; i < length; i++)
1412 float mean = sum / (float)length;
1414 for (uint16_t i = 0U; i < length; i++)
1416 float error = data[i] - mean;
1417 sq_err_sum += error * error;
1420 variance = sq_err_sum / (float)length;
1439 else if (value < min)
1457 float real_sum = 0.0f;
1458 float imag_sum = 0.0f;
1460 for (uint16_t i = 0U; i < num_steps; i++)
1462 real_sum += (float)data[i * stride].real;
1463 imag_sum += (float)data[i * stride].imag;
1466 *out = real_sum + (imag_sum * I);
1473 float real_mean = crealf(*out) / (float)num_steps;
1474 float imag_mean = cimagf(*out) / (float)num_steps;
1476 *out = real_mean + (imag_mean * I);
1479 static void rfft(
const float *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride)
1481 small_rfft(data, data_length, length_shift - 1U, output, stride);
1485 output[(((uint16_t)1U) << (length_shift - 1U)) * stride] = cimagf(output[0]);
1486 output[0] = crealf(output[0]);
1489 static void fftshift(
float *data, uint16_t data_length, uint16_t stride)
1491 uint16_t half_data_length = (data_length + 1U) / 2U;
1493 for (uint16_t i = 0U; i < half_data_length; i++)
1497 for (uint16_t j = 0U; j < (data_length - 1U); j++)
1499 data[j * stride] = data[(j * stride) + stride];
1502 data[(data_length * stride) - stride] = x;
1506 static void welch(
const float complex *data,
1507 uint16_t data_length,
1508 uint16_t segment_length,
1509 float complex *data_buffer,
1510 float complex *fft_out,
1512 const float *window,
1513 uint16_t length_shift,
1517 uint16_t num_segments = data_length / segment_length;
1520 for (uint16_t i = 0U; i < num_segments; i++)
1523 float complex mean = 0.0f;
1525 for (uint16_t j = 0U; j < segment_length; j++)
1527 mean += data[(i * segment_length * stride) + (j * stride)];
1530 float complex adj_mean_real = crealf(mean) / (float)segment_length;
1531 float complex adj_mean_imag = cimagf(mean) / (float)segment_length;
1532 mean = adj_mean_real + (adj_mean_imag * I);
1534 for (uint16_t j = 0U; j < segment_length; j++)
1536 data_buffer[j] = data[(i * segment_length * stride) + (j * stride)] - mean;
1538 float complex adj_buf_real = crealf(data_buffer[j]) * window[j];
1539 float complex adj_buf_imag = cimagf(data_buffer[j]) * window[j];
1540 data_buffer[j] = adj_buf_real + (adj_buf_imag * I);
1542 scale += window[j] * window[j];
1547 for (uint16_t j = 0U; j < segment_length; j++)
1549 psd[j * stride] += cabsf(fft_out[j]) * cabsf(fft_out[j]);
1555 scale = 1.0f / (scale * fs * (float)num_segments);
1558 for (uint16_t i = 0U; i < segment_length; i++)
1560 psd[i * stride] *= scale;
1566 float x = data[sample_idx];
1569 y = state[0] + (b[0] * x);
1571 state[0] = state[1] + (b[1] * x) - (a[0] * y);
1572 state[1] = state[2] + (b[2] * x) - (a[1] * y);
1573 state[2] = state[3] + (b[3] * x) - (a[2] * y);
1574 state[3] = (b[4] * x) - (a[3] * y);
1576 data[sample_idx] = y;
1583 uint16_t i = index * 2U;
1585 if (i < data_length)
1587 real = data[i * stride];
1592 if (i < data_length)
1594 imag = data[i * stride];
1597 return real + (imag * I);
1602 float complex res = 0.0f + 0.0f * I;
1604 if (index < data_length)
1606 res = data[index * stride];
1612 static void small_rfft(
const float *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride)
1614 uint16_t full_data_length = ((uint16_t)1U) << length_shift;
1616 if (length_shift == 0U)
1621 else if (length_shift == 1U)
1626 output[1U * stride] =
1632 uint16_t reverse_i = 0U;
1633 for (uint16_t i = 0U; i < full_data_length; i++)
1639 output[reverse_i * stride] = tmp;
1641 else if (i == reverse_i)
1650 uint16_t bit = full_data_length >> 1U;
1651 while ((bit & reverse_i) != 0U)
1663 static void small_fft(
const float complex *data, uint16_t data_length, uint16_t length_shift,
float complex *output, uint16_t stride)
1665 uint16_t full_data_length = ((uint16_t)1U) << length_shift;
1667 if (length_shift == 0U)
1672 else if (length_shift == 1U)
1681 uint16_t reverse_i = 0U;
1682 for (uint16_t i = 0U; i < full_data_length; i++)
1688 output[reverse_i * stride] = tmp;
1690 else if (i == reverse_i)
1699 uint16_t bit = full_data_length >> 1U;
1700 while ((bit & reverse_i) != 0U)
1714 uint16_t full_data_length = ((uint16_t)1U) << length_shift;
1717 for (uint16_t i = 0U; i < full_data_length; i += 4U)
1719 float complex s0 = output[i * stride] + output[(i + 1U) * stride];
1720 float complex d0 = output[i * stride] - output[(i + 1U) * stride];
1721 float complex s1 = output[(i + 2U) * stride] + output[(i + 3U) * stride];
1722 float complex d1 = output[(i + 2U) * stride] - output[(i + 3U) * stride];
1724 d1 = cimagf(d1) - (I * crealf(d1));
1726 output[(i + 0U) * stride] = s0 + s1;
1727 output[(i + 2U) * stride] = s0 - s1;
1728 output[(i + 1U) * stride] = d0 + d1;
1729 output[(i + 3U) * stride] = d0 - d1;
1733 uint16_t block_length = 4U;
1734 float complex phase_incr = -I;
1736 while (block_length < full_data_length)
1739 phase_incr = (phase_incr + 1.0f) / cabsf(phase_incr + 1.0f);
1741 float complex phase = 1.0f;
1742 for (uint16_t m = 0U; m < block_length; m++)
1744 for (uint16_t i = m; i < full_data_length; i += block_length << 1U)
1746 float complex delta = output[(i + block_length) * stride] * phase;
1748 output[(i + block_length) * stride] = output[i * stride] - delta;
1750 output[i * stride] += delta;
1754 phase = phase * phase_incr;
1757 block_length <<= 1U;
1763 uint16_t full_data_length = ((uint16_t)1U) << length_shift;
1765 output[0] = (1.0f + (1.0f * I)) * conjf(output[0]);
1767 if (length_shift > 0U)
1769 float complex phase_incr = I;
1770 float complex z1_factor = 0.5f * phase_incr;
1772 for (uint16_t i = 1U; i < length_shift; i++)
1774 phase_incr = (phase_incr + 1.0f) / cabsf(phase_incr + 1.0f);
1777 uint16_t mid = full_data_length / 2U;
1778 for (uint16_t i = 1U; i < mid; i++)
1781 float complex z0 = output[i * stride];
1782 float complex z1 = output[(full_data_length - i) * stride];
1785 z1 = conjf(z0) - z1;
1789 z1_factor = z1_factor * phase_incr;
1790 z1 = z1 * z1_factor;
1793 z1 = conjf(z0) - z1;
1796 output[i * stride] = z0;
1797 output[(full_data_length - i) * stride] = z1;
1800 output[mid * stride] = conjf(output[mid * stride]);
1805 const uint16_t num_points,
1806 const uint16_t sweep,
1807 const uint16_t point,
1808 const uint16_t median_start_sweep)
1811 int32_t point_r[4U];
1812 int32_t point_i[4U];
1813 int32_t point_abs[4U];
1816 for (uint16_t idx = 0U; idx < 4U; idx++)
1818 point_r[idx] = frame[((median_start_sweep + idx) * num_points) + point].
real;
1819 point_i[idx] = frame[((median_start_sweep + idx) * num_points) + point].
imag;
1820 point_abs[idx] = (point_r[idx] * point_r[idx]) + (point_i[idx] * point_i[idx]);
1823 uint16_t high_index = 0U;
1824 uint16_t low_index = 0U;
1825 int32_t high_val = INT32_MIN;
1826 int32_t low_val = INT32_MAX;
1829 for (uint16_t idx = 0; idx < 4U; idx++)
1831 if (point_abs[idx] > high_val)
1833 high_val = point_abs[idx];
1837 if (point_abs[idx] < low_val)
1839 low_val = point_abs[idx];
1845 point_r[high_index] = 0;
1846 point_i[high_index] = 0;
1847 point_r[low_index] = 0;
1848 point_i[low_index] = 0;
1850 int32_t median_real = 0;
1851 int32_t median_imag = 0;
1854 for (uint16_t idx = 0U; idx < 4U; idx++)
1856 median_real += point_r[idx];
1857 median_imag += point_i[idx];
1861 median_real = median_real / 2;
1862 median_imag = median_imag / 2;
1864 frame[(sweep * num_points) + point].real = (int16_t)median_real;
1865 frame[(sweep * num_points) + point].imag = (int16_t)median_imag;
1869 const uint16_t sweeps_per_frame,
1870 const uint16_t num_points,
1871 const uint16_t sweep,
1872 const uint16_t point)
1875 int32_t interpolate_real_i32 = frame[((sweep - 1U) * num_points) + point].
real;
1876 int32_t interpolate_imag_i32 = frame[((sweep - 1U) * num_points) + point].
imag;
1878 interpolate_real_i32 = interpolate_real_i32 * 2;
1879 interpolate_imag_i32 = interpolate_imag_i32 * 2;
1882 uint16_t sweep_idx = sweep + 2U;
1884 if (sweep_idx > (sweeps_per_frame - 1U))
1886 sweep_idx = sweeps_per_frame - 1U;
1889 interpolate_real_i32 += frame[((sweep_idx)*num_points) + point].
real;
1890 interpolate_imag_i32 += frame[((sweep_idx)*num_points) + point].
imag;
1892 interpolate_real_i32 = interpolate_real_i32 / 3;
1893 interpolate_imag_i32 = interpolate_imag_i32 / 3;
1896 frame[(sweep * num_points) + point].real = (int16_t)interpolate_real_i32;
1897 frame[(sweep * num_points) + point].imag = (int16_t)interpolate_imag_i32;
1902 const float *velocities,
1903 const float *energies,
1904 const uint16_t *peak_idxs,
1905 float *merged_velocities,
1906 float *merged_energies,
1907 uint16_t cluster_count)
1909 float min = INFINITY;
1910 float max = -INFINITY;
1912 for (uint16_t i = 0U; i < num_peaks; i++)
1914 merged_velocities[cluster_count] += velocities[peak_idxs[start_idx + i]];
1915 merged_energies[cluster_count] += energies[peak_idxs[start_idx + i]];
1917 min = fminf(velocities[peak_idxs[start_idx + i]], min);
1919 max = fmaxf(velocities[peak_idxs[start_idx + i]], max);
1922 merged_velocities[cluster_count] /= (float)num_peaks;
1923 merged_energies[cluster_count] /= (float)num_peaks;
1987 static void sort_i16(int16_t *array, uint16_t array_length)
1989 for (uint16_t i = 0; i < (array_length - 1U); i++)
1991 for (uint16_t j = 0; j < (array_length - i - 1U); j++)
1993 if (array[j] > array[j + 1U])
2001 static void swap_i16(int16_t *array, uint16_t idx_a, uint16_t idx_b)
2003 int16_t tmp = array[idx_a];
2005 array[idx_a] = array[idx_b];
2009 static void sort_f32(
float *array, uint16_t array_length)
2011 for (uint16_t i = 0; i < (array_length - 1U); i++)
2013 for (uint16_t j = 0; j < (array_length - i - 1U); j++)
2015 if (array[j] > array[j + 1U])
2023 static void swap_f32(
float *array, uint16_t idx_a, uint16_t idx_b)
2025 float tmp = array[idx_a];
2027 array[idx_a] = array[idx_b];