fork download
  1. #include <stdio.h>
  2.  
  3. #define FS 25 //sampling frequency
  4. #define BUFFER_SIZE (FS* 2)
  5.  
  6.  
  7. int min(int x, int y){
  8. if (x<y){
  9. return x;
  10. }
  11. else{return y;}
  12. }
  13. //maxim_find_peaks( an_ir_valley_locs, &n_npks, an_x = avg.ir, BUFFER_SIZE, n_th1, 4, 15 );//peak_height, peak_distance, max_num_peaks
  14. void printArr(int *arr, int count){
  15. int i = 0;
  16. printf("[");
  17. while(i < count){
  18. printf(" %d", arr[i]);
  19. i++;
  20. }
  21. printf(" ]\n");
  22. }
  23.  
  24.  
  25. void maxim_peaks_above_min_height( int *pn_locs, int *n_npks, int *pn_x, int n_size, int n_min_height )
  26. /**
  27. * \brief Find peaks above n_min_height
  28. * \par Details
  29. * Find all peaks above MIN_HEIGHT
  30. *
  31. * \retval None
  32. */
  33. {
  34. int i = 1, n_width;
  35. *n_npks = 0;
  36.  
  37. while (i < n_size-1){
  38. if (pn_x[i] > n_min_height && pn_x[i] > pn_x[i-1]){ // find left edge of potential peaks
  39. n_width = 1;
  40. while (i+n_width < n_size && pn_x[i] == pn_x[i+n_width]) // find flat peaks
  41. n_width++;
  42. if (pn_x[i] > pn_x[i+n_width] && (*n_npks) < 15 ){ // find right edge of peaks
  43. pn_locs[(*n_npks)++] = i;
  44. // for flat peaks, peak location is left edge
  45. i += n_width+1;
  46. }
  47. else
  48. i += n_width;
  49. }
  50. else
  51. i++;
  52. }
  53. }
  54.  
  55.  
  56. void maxim_sort_ascend(int *pn_x, int n_size)
  57. /**
  58. * \brief Sort array
  59. * \par Details
  60. * Sort array in ascending order (insertion sort algorithm)
  61. *
  62. * \retval None
  63. */
  64. {
  65.  
  66. int i, j, n_temp;
  67. for (i = 1; i < n_size; i++) {
  68. n_temp = pn_x[i];
  69. for (j = i; j > 0 && n_temp < pn_x[j-1]; j--)
  70. pn_x[j] = pn_x[j-1];
  71. pn_x[j] = n_temp;
  72. }
  73. }
  74.  
  75. void maxim_sort_indices_descend( int *pn_x, int *pn_indx, int n_size)
  76. /**
  77. * \brief Sort indices
  78. * \par Details
  79. * Sort indices according to descending order (insertion sort algorithm)
  80. *
  81. * \retval None
  82. */
  83. {
  84.  
  85. int i, j, n_temp;
  86. for (i = 1; i < n_size; i++) {
  87. n_temp = pn_indx[i];
  88. for (j = i; j > 0 && pn_x[n_temp] > pn_x[pn_indx[j-1]]; j--)
  89. pn_indx[j] = pn_indx[j-1];
  90. pn_indx[j] = n_temp;
  91. }
  92. }
  93.  
  94.  
  95. void maxim_remove_close_peaks(int *pn_locs, int *pn_npks, int *pn_x, int n_min_distance)
  96. /**
  97. * \brief Remove peaks
  98. * \par Details
  99. * Remove peaks separated by less than MIN_DISTANCE
  100. *
  101. * \retval None
  102. */
  103. {
  104. //maxim_remove_close_peaks( pn_locs = loclist, n_npks = count, pn_x = ir, n_min_distance = dis );
  105. int i, j, n_old_npks, n_dist;
  106.  
  107. /* Order peaks from large to small */
  108.  
  109.  
  110. //maxim_remove_close_peaks( pn_locs = list, pn_npks = count, pn_x = ir, n_min_distance = min );
  111.  
  112. maxim_sort_indices_descend( pn_x, pn_locs, *pn_npks );
  113.  
  114. printArr(pn_locs, *pn_npks);
  115. for ( i = -1; i < *pn_npks; i++ ){
  116. n_old_npks = *pn_npks;
  117. *pn_npks = i+1;
  118. for ( j = i+1; j < n_old_npks; j++ ){
  119. n_dist = pn_locs[j] - ( i == -1 ? -1 : pn_locs[i] ); // lag-zero peak of autocorr is at index -1
  120. if ( n_dist > n_min_distance || n_dist < -n_min_distance )
  121. pn_locs[(*pn_npks)++] = pn_locs[j];
  122. }
  123. }
  124. printArr(pn_locs, *pn_npks);
  125. // Resort indices into ascending order
  126. maxim_sort_ascend( pn_locs, *pn_npks );
  127. printArr(pn_locs, *pn_npks);
  128. }
  129.  
  130. void maxim_find_peaks( int *pn_locs, int *n_npks, int *pn_x, int n_size, int n_min_height, int n_min_distance, int n_max_num )
  131. /**
  132. * \brief Find peaks
  133. * \par Details
  134. * Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE
  135. *
  136. * \retval None
  137. */
  138. {
  139. maxim_peaks_above_min_height( pn_locs, n_npks, pn_x, n_size, n_min_height );
  140. printf("Above min arr: ");
  141. printArr(pn_locs, *n_npks);
  142. maxim_remove_close_peaks( pn_locs, n_npks, pn_x, n_min_distance );
  143. printf("remove close :");
  144. printArr(pn_locs, *n_npks);
  145. *n_npks = min( *n_npks, n_max_num );
  146. }
  147.  
  148. void maxim_heart_rate_and_oxygen_saturation(unsigned int *pun_ir_buffer, int n_ir_buffer_length,
  149. int *pn_heart_rate, int *pch_hr_valid, int unsigned *an_x)
  150. {
  151. unsigned int un_ir_mean,un_only_once ;
  152. int k, n_i_ratio_count;
  153. int i, s, m, n_exact_ir_valley_locs_count, n_middle_idx;
  154. int n_th1, n_npks, n_c_min;
  155. int an_ir_valley_locs[15] ;
  156. int n_peak_interval_sum;
  157.  
  158. int n_y_ac, n_x_ac;
  159. int n_spo2_calc;
  160. int n_y_dc_max, n_x_dc_max;
  161. int n_y_dc_max_idx, n_x_dc_max_idx;
  162. int an_ratio[5], n_ratio_average;
  163. int n_nume, n_denom ;
  164.  
  165. // calculates DC mean and subtract DC from ir
  166. un_ir_mean =0;
  167. for (k=0 ; k<n_ir_buffer_length ; k++ ) un_ir_mean += pun_ir_buffer[k] ;
  168. un_ir_mean =un_ir_mean/n_ir_buffer_length ;
  169. printf("mean is %d\n",un_ir_mean);
  170.  
  171. // remove DC and invert signal so that we can use peak detector as valley detector
  172. for (k=0 ; k<n_ir_buffer_length ; k++ )
  173. an_x[k] = -1*(pun_ir_buffer[k] - un_ir_mean) ;
  174.  
  175. printf("ir array, dc removed ");
  176. printArr(an_x, 50);
  177. // 4 pt Moving Average
  178. for(k=0; k< BUFFER_SIZE-4; k++){
  179. an_x[k]=( an_x[k]+an_x[k+1]+ an_x[k+2]+ an_x[k+3])/(int)4;
  180. }
  181. // calculate threshold
  182. n_th1=0;
  183. for ( k=0 ; k<BUFFER_SIZE ;k++){
  184. n_th1 += an_x[k];
  185. }
  186. n_th1= n_th1/ ( BUFFER_SIZE);
  187. printf("min is %d\n", n_th1);
  188. if( n_th1<30) n_th1=30; // min allowed
  189. if( n_th1>60) n_th1=60; // max allowed
  190.  
  191. for ( k=0 ; k<15;k++) an_ir_valley_locs[k]=0;
  192. // since we flipped signal, we use peak detector as valley detector
  193.  
  194.  
  195. printf("Array for averaged ir is ");
  196. printArr(an_x, 50);
  197.  
  198.  
  199. maxim_find_peaks( an_ir_valley_locs, &n_npks, an_x, BUFFER_SIZE, n_th1, 4, 15 );//peak_height, peak_distance, max_num_peaks
  200.  
  201. printf("Array for list is");
  202. printArr(an_ir_valley_locs, n_npks);
  203.  
  204. n_peak_interval_sum =0;
  205. if (n_npks>=2){
  206. for (k=1; k<n_npks; k++) n_peak_interval_sum += (an_ir_valley_locs[k] -an_ir_valley_locs[k -1] ) ;
  207. n_peak_interval_sum =n_peak_interval_sum/(n_npks-1);
  208. *pn_heart_rate =(int)( (FS*60)/ n_peak_interval_sum );
  209. *pch_hr_valid = 1;
  210. }
  211. else {
  212. *pn_heart_rate = -999; // unable to calculate because # of peaks are too small
  213. *pch_hr_valid = 0;
  214. }
  215. }
  216.  
  217.  
  218. int main(void) {
  219. // your code goes here
  220.  
  221. int ir[50] = {6232, 13423, 319, 8754, 3660, 15297, 321, 1028, 2250, 2828, 7738, 5072, 2127, 7393, 76, 12470, 5088, 902, 16257, 15355, 6248, 9790, 5723, 7578, 8159, 7071, 4029, 5814, 7005, 10472, 11111, 6675, 9635, 15670, 643, 4874, 4433, 9862, 15868, 10150, 12961, 15544, 961, 1341, 15611, 6682, 1158, 2765, 9992, 9486};
  222. int count = 0;
  223. unsigned int list[15];
  224. int hr = 0;
  225. int valid = 0;
  226. int irA[50];
  227. maxim_heart_rate_and_oxygen_saturation(ir,50,&hr, &valid, irA);
  228. /*
  229. maxim_peaks_above_min_height(list, &count, ir, 50, 10000 );
  230. printArr(list, count);
  231. maxim_remove_close_peaks(list, &count, ir, 4);
  232. */
  233. printf("Hr is %d\n", hr);
  234. printf("Hr valid is %d\n", valid);
  235. return 0;
  236. }
  237.  
  238.  
Success #stdin #stdout 0s 2172KB
stdin
Standard input is empty
stdout
mean is 7278
ir array, dc removed [ 1046 -6145 6959 -1476 3618 -8019 6957 6250 5028 4450 -460 2206 5151 -115 7202 -5192 2190 6376 -8979 -8077 1030 -2512 1555 -300 -881 207 3249 1464 273 -3194 -3833 603 -2357 -8392 6635 2404 2845 -2584 -8590 -2872 -5683 -8266 6317 5937 -8333 596 6120 4513 -2714 -2208 ]
min is 134
Array for averaged ir is [ 96 739 270 270 2201 2554 5671 3817 2806 2836 1695 3611 1761 1021 2644 1073740422 1073739701 1073739411 1073737189 1073739823 1073741767 1073741289 145 568 1009 1298 448 1073740501 1073740286 1073739628 1073738329 1073740946 1073741396 873 2325 1073740342 1073739023 1073736891 1073735471 1073739198 1073741400 1073740737 1129 1080 724 2128 6120 4513 -2714 -2208 ]
Above min arr: [ 1 6 9 11 15 20 25 27 32 35 40 46 ]
[ 20 40 32 27 15 35 46 6 11 9 25 1 ]
[ 20 40 32 27 15 46 6 ]
[ 6 15 20 27 32 40 46 ]
remove close :[ 6 15 20 27 32 40 46 ]
Array for list is[ 6 15 20 27 32 40 46 ]
Hr is 250
Hr valid is 1