#include /* Standard input/output definitions */ #include #include /* Standard types */ #include /* String function definitions */ #include /* UNIX standard function definitions */ #include /* File control definitions */ #include /* Error number definitions */ #include /* POSIX terminal control definitions */ #include #include #include "lo/lo.h" int serialport_init(const char *serialport, int baud); int serialport_read_until(int fd, char* buf, char until); int shift_buffer(int *frame, int hop, int bsize); int return_val(int baudrate, const char *serialport, int fd, int bsize); int min(int var_array[], int len_var_array); int max(int var_array[], int len_var_array); float max_index(int var_array[], int len_var_array); int mean_array(int array[], int start, int end); int *adapt_thresh(int buffer[], int bsize, int smoothing_factor); int *str_to_int(char *line, char *deliminator); int *autocorrelation(int sensor_array[], int bsize); int *rayleigh_win(int acf[], int center_lag, int bsize); int *peak_pick(int win_acf[], int bsize); int main() // main function { lo_address t = lo_address_new(NULL, "7770"); int baudrate = 9600; const char *serialport = "/dev/cu.usbserial-A7007bfP"; int fd = 0; fd = serialport_init(serialport, baudrate); // serialport initialization if (fd==-1) return -1; int frame_flag = 0; // if 0, then first frame. otherwise frame > 0, and perform shift_buffer. int bsize = 512; // buffersize int hop = bsize/4; // hop size for windowing function of sensor int buffer[bsize]; // buffer creation int *frame = malloc(bsize * sizeof(int)); // pointer allocation for buffer frame int *sensor_smooth; int *sensor_smooth_1; int *sensor_smooth_2; int tempo, tempo_old = 0;//, tempo_older = 0; // tempo is generated from current tempo, tempo old = tempo from previous frame int smoothing_factor = 8; // originally set to 8, this rounds off peaks int *acf; int *win_acf; float period;//, period_old, period_older = 0; float resample_amt = 4.59375; // 44100 / 9600 ... to get equivalent value for audio control int center_lag = 80; // center point for rayleigh weighting int adj_weight; int avg_tempo; printf("start walking and hit return..."); getchar(); // main loop while(1) { int i = 0; // for buffer iteration if (frame_flag > 0) { // tempo_old = tempo; // previously determined tempo = tempo_old frame = &buffer[0]; shift_buffer(frame, hop, bsize); // after first frame, samples @256-511 are moved to locations 0-255 for (i=hop; i < bsize; i++) { // following relocation, fill in remaining samples buffer[i] = return_val(baudrate, serialport, fd, bsize); } frame_flag++; } else if (frame_flag < 1) { // for the first frame, sensor data is extracted for (i = 0; i < bsize; i++) { buffer[i] = return_val(baudrate, serialport, fd, bsize); } frame_flag++; } sensor_smooth = adapt_thresh(buffer, bsize, smoothing_factor); // adaptive thresholding smooths the sensor data acf = autocorrelation(sensor_smooth, bsize); // autocorrelation function win_acf = rayleigh_win(acf, center_lag, bsize); // Rayleigh weighting around a center lag period = max_index(win_acf, bsize); // retrieve the highest peak from the processed buffer tempo = (60 / ((period*bsize/(baudrate*resample_amt))) * 2); // tempo of footstep 2x for 2 feet *** ACF method // adj_weight = center_lag - period; // prepare value to shift center lag by // // if (abs(adj_weight) > period/3) { // if value is within reasonable amount // center_lag += (adj_weight/4); // start moving weighting center towards newly found period // } // some hacks to keep tempo in line if (tempo > tempo_old) { if ((tempo - tempo_old) > (tempo_old/3)) { tempo = tempo / 2; } } else { // if old tempo is greater than new if ((tempo_old - tempo) > (tempo_old/3)) {// and if difference is greater than 1/3 old tempo tempo = tempo * 2; } } if (tempo > 180) { // if tempo is > 180, 1/2 it tempo = tempo/2; } if (tempo < 70) { // if tempo is < 70, 2x it tempo = tempo*2; } printf("tempo:%d\n", tempo); if (lo_send(t, "/sensor/tempo", "i", tempo) == -1) { // using osc, send out tempo on address 7770 printf("OSC error %d: %s\n", lo_address_errno(t), lo_address_errstr(t)); } tempo_old = tempo; // preserve newfound tempo to prevent against next cycle's outliers } free (frame); } int *peak_pick(int array[], int bsize) // returns array of 0 and >0 values at peak points { int *peaks = malloc(bsize * sizeof(bsize)); int i; for (i = 0; i < bsize; i++) { if ((array[i] > array[i-1]) && (array[i] > array[i+1])) { peaks[i] = array[i]; } else { peaks[i] = 0; } } return peaks; } int *rayleigh_win(int acf[], int center_lag, int bsize) { int *win_acf = malloc(bsize * sizeof(int)); float w[bsize]; float twopi = 6.28; int i,n; double t1,t2; for (i = 0; i < bsize; i++) { n = i+1; t1 = n / pow(center_lag,2); t2 = (-1 * (pow(-n,2))) / (2 * pow(center_lag,2)); w[i] = t1 *exp(t2); win_acf[i] = w[i] * acf[i]; } return win_acf; } int *autocorrelation(int sensor_array[], int bsize) { int *acf = malloc(bsize * sizeof(int)); int sum; int i,j; for (i=0; i ans){ ans = var_array[i]; } } return ans; } float max_index(int var_array[], int len_var_array) { int i; int max_val = var_array[0]; float max_index = 0; for (i=0; i < len_var_array; i++) { if (var_array[i] > max_val){ max_val = var_array[i]; max_index = i; } } return max_index; }