fit_f0.m 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. function [f0slope,sfm_amp,sfm_frq,sfm_phase]=fit_f0(f0data, ploton);
  2. % this function tries to fit f0 as a function of time with a combination of
  3. % a linear fm plus a sinusoidal fm;
  4. % input is an x by 2 matrix with the time values in the first column and
  5. % the corresponding f0 values in the 2nd column
  6. % the matrix must have at least 5 rows
  7. % outputs are four values
  8. % 1st output: linear fm slope (in kHz/ms)
  9. % 2nd output: amplitude of sfm (in kHz)
  10. % 3rd output: frequency of SFM component (in Hz)
  11. % 4th output: phase of SFM component (in rad)
  12. if size(f0data,1)>5,
  13. % fit a linear regression
  14. [p,s]=polyfit(f0data(:,1),f0data(:,2),1);
  15. f0slope=p(1)/1e6; % in kHz per millisecond
  16. linfit=polyval(p,f0data(:,1));
  17. if ploton==1,
  18. figure(1),
  19. subplot(2,1,1);
  20. plot(f0data(:,1),f0data(:,2),f0data(:,1),linfit);
  21. title(['f0 slope = ' num2str(f0slope) ' kHz/ms']);
  22. end
  23. % fit a sinusoid to the residual
  24. x=f0data(:,1)-min(f0data(:,1)); % reset time to start at 0
  25. y=f0data(:,2)-linfit;
  26. % estimate for sfm_amp
  27. b0(1)=(max(y)-min(y))/2;
  28. % estimate for sfm_freq
  29. b0(2)= 1/(mean(diff(find(diff(sign(y)))))*2*mean(diff(x)));
  30. % estimate for sfm_phase
  31. if diff(y(1:2))>0
  32. b0(3)=0;
  33. else
  34. b0(3)=1;
  35. end
  36. b=nlinfit(x,y,@(b,x) b(1).*sin(2*pi*x*b(2)+b(3)*pi),b0);
  37. sinfit=b(1).*sin(2*pi*x*b(2)+b(3)*pi);
  38. sfm_amp=b(1)/1e3; % SFM Amplitude (kHz)
  39. sfm_frq=b(2);
  40. sfm_phase=b(3);
  41. if ploton==1,
  42. figure(1),
  43. subplot(2,1,2);
  44. plot(x,y,'b', x,sinfit, 'r')
  45. title(['SFM FRQ = ' num2str(sfm_frq) ' Hz; SFM AMP = ' num2str(sfm_amp) ' kHz']);
  46. end
  47. else
  48. f0slope=nan;
  49. sfm_amp=nan;
  50. sfm_frq=nan;
  51. sfm_phase=nan;
  52. end