/* peak-tracking.c * atsa: ATS analysis implementation * Oscar Pablo Di Liscia / Pete Moss / Juan Pampin */ #include "atsa.h" #include #include /* private function prototypes */ ATS_PEAK *find_candidates(ATS_PEAK *peaks, int peaks_size, double lo, double hi, int *cand_size); ATS_PEAK *find_best_candidate(ATS_PEAK *peak_candidates, int cand_size, double peak_frq, double peak_smr, double alpha, ATS_PEAK *tracks, int tracks_size); #define LARGEST_DOUBLE 1.7976931348623157e308 /* peak_tracking * ============= * connects peaks from one analysis frame to tracks * returns a pointer to the analysis frame. * tracks: pointer to the tracks * tracks_size: numeber of tracks * peaks: peaks to connect * peaks_size: number of peaks * frq_dev: frequency deviation from tracks * SMR_cont: contribution of SMR to tracking * n_partials: pointer to the number of partials before tracking */ ATS_FRAME *peak_tracking(ATS_PEAK *tracks, int tracks_size, ATS_PEAK *peaks, int *peaks_size, double frq_dev, double SMR_cont, int *n_partials) { ATS_PEAK track, *matched_peak = NULL, *peak_candidates = NULL; double track_frq, track_smr, lo, hi; int i, k, j, cand_size; ATS_FRAME *returned_peaks = (ATS_FRAME *)malloc(2*sizeof(ATS_FRAME)); returned_peaks[0].peaks = returned_peaks[1].peaks = NULL; returned_peaks[0].n_peaks = returned_peaks[1].n_peaks = 0; if(tracks_size && *peaks_size) { qsort(peaks, *peaks_size, sizeof(ATS_PEAK), peak_frq_inc); for (k=0; kfrq) { if( matched_peak->track >= 0){ /* put previously holding track into unmatched peaks */ for(j=0; jtrack) break; } returned_peaks[0].peaks = push_peak(&tracks[j], returned_peaks[0].peaks, &returned_peaks[0].n_peaks); } peaks[i].track = track.track; break; } } else { returned_peaks[0].peaks = push_peak(&track, returned_peaks[0].peaks, &returned_peaks[0].n_peaks); } free(peak_candidates); peak_candidates = NULL; } } for(i=0; i<*peaks_size; i++) if(peaks[i].track < 0) { peaks[i].track = (*n_partials)++; returned_peaks[1].peaks = push_peak(&peaks[i], returned_peaks[1].peaks, &returned_peaks[1].n_peaks); } return(returned_peaks); } /* find_candidates * =============== * find candidates to continue a track form an array of peaks * returns a pointer to an array of candidates * peaks: pointer to array of peaks * peaks_size: number of peaks * lo: lowest frequency to consider candidates * hi: highest frequency to consider candidates * cand_size: pointer to the number of candidates returned * Note: this function assumes peaks were sorted * by increasing freq by caller */ ATS_PEAK *find_candidates(ATS_PEAK *peaks, int peaks_size, double lo, double hi, int *cand_size) { int i; ATS_PEAK *cand_list = NULL; for(i=0; i= 0) { /* find track holding candidate */ for(k=0; k ((fabs(tracks[k].frq - peak_candidates[i].frq) + (SMR_cont * fabs(tracks[k].smr - peak_candidates[i].smr))) / (SMR_cont + 1))) { continue; } } if(local_delta < delta) { best_peak = &peak_candidates[i]; delta = local_delta; } } return(best_peak); } /* update_tracks * ============= * updates analysis tracks * returns a pointer to the tracks. * tracks: pointer to the tracks * tracks_size: numeber of tracks * track_len: length of tracks * frame_n: analysis frame number * ana_frames: pointer to previous analysis frames * last_peak_cont: contribution of last peak to the track */ ATS_PEAK *update_tracks (ATS_PEAK *tracks, int *tracks_size, int track_len, int frame_n, ATS_FRAME *ana_frames, double last_peak_cont) { int frames, first_frame, track, g, i, k; double frq_acc, last_frq, amp_acc, last_amp, smr_acc, last_smr; int f, a, s; ATS_PEAK *l_peaks, *peak; if (tracks != NULL) { frames = (frame_n < track_len) ? frame_n : track_len; first_frame = frame_n - frames; for(g=0; g<*tracks_size; g++) { track = tracks[g].track; frq_acc = last_frq = amp_acc = last_amp = smr_acc = last_smr = 0.0; f = a = s = 0; for(i=first_frame; ifrq > 0.0) { last_frq = peak->frq; frq_acc += peak->frq; f++; } if (peak->amp > 0.0) { last_amp = peak->amp; amp_acc += peak->amp; a++; } if (peak->smr > 0.0) { last_smr = peak->smr; smr_acc += peak->smr; s++; } } } if(f) tracks[g].frq = (last_peak_cont * last_frq) + ((1 - last_peak_cont) * (frq_acc / f)); if(a) tracks[g].amp = (last_peak_cont * last_amp) + ((1 - last_peak_cont) * (amp_acc / a)); if(s) tracks[g].smr = (last_peak_cont * last_smr) + ((1 - last_peak_cont) * (smr_acc / s)); } } else for(g=0; g