annotate aim-mat/modules/usermodule/pitchstrength/PeakPicker.m @ 4:537f939baef0 tip

various bug fixes and changed copyright message
author Stefan Bleeck <bleeck@gmail.com>
date Tue, 16 Aug 2011 14:37:17 +0100
parents
children
rev   line source
bleeck@4 1 %
bleeck@4 2 % function out = PeakPicker(sig_in, params)
bleeck@4 3 %
bleeck@4 4 % Find the peaks of a signal
bleeck@4 5 %
bleeck@4 6 % INPUT VALUES:
bleeck@4 7 % sig_in Input signal
bleeck@4 8 % params.dyn_thresh dynamic threshold. Off if not used
bleeck@4 9 % params.smooth_sigma sigma for smoothing
bleeck@4 10 %
bleeck@4 11 %
bleeck@4 12 %
bleeck@4 13 %
bleeck@4 14 % RETURN VALUE:
bleeck@4 15 % out is an array of a struct
bleeck@4 16 % out.x x position of the Peak
bleeck@4 17 % out.t according time value
bleeck@4 18 % out.y y value of the peak
bleeck@4 19 % out.left.[x,t,y] left Minumum
bleeck@4 20 % out.right.[x,t,y] right Minumum
bleeck@4 21 %
bleeck@4 22 % (c) 2003, University of Cambridge, Medical Research Council
bleeck@4 23 % Christoph Lindner
bleeck@4 24 % (c) 2011, University of Southampton
bleeck@4 25 % Maintained by Stefan Bleeck (bleeck@gmail.com)
bleeck@4 26 % download of current version is on the soundsoftware site:
bleeck@4 27 % http://code.soundsoftware.ac.uk/projects/aimmat
bleeck@4 28 % documentation and everything is on http://www.acousticscale.org
bleeck@4 29
bleeck@4 30 function out = PeakPicker(sig_in, params)
bleeck@4 31
bleeck@4 32 if nargin<2
bleeck@4 33 params=[];
bleeck@4 34 end
bleeck@4 35
bleeck@4 36 % % % % ----- Other Parameters -----
bleeck@4 37 % % % % Lowpass param for the higpassfilter
bleeck@4 38 % % % LP_sigma_for_HP_filter = getnrpoints(sig_in)/7;
bleeck@4 39 % % % LP_sigma_for_smooth = 3;
bleeck@4 40 % % % % min width of a peak: upper_threshold+lower_thresh
bleeck@4 41 % % % upper_thresh = 0.02*getnrpoints(sig_in);
bleeck@4 42 % % % lower_thresh = 0.03*getnrpoints(sig_in);
bleeck@4 43
bleeck@4 44 % x is index or position in vector
bleeck@4 45 % y is value of the
bleeck@4 46 % t is the time domain wich is assigned to the x dimension
bleeck@4 47
bleeck@4 48 % the original values befor filtering
bleeck@4 49 orig_values = getdata(sig_in)';
bleeck@4 50
bleeck@4 51 if isfield(params,'smooth_sigma')
bleeck@4 52 if (params.smooth_sigma~=0)
bleeck@4 53 % smooth the curve to kill small side peaks
bleeck@4 54 sig_in = smooth(sig_in, params.smooth_sigma);
bleeck@4 55 end
bleeck@4 56 end
bleeck@4 57
bleeck@4 58 values=getdata(sig_in)';
bleeck@4 59
bleeck@4 60 % ------------------- Find the local maxima ------------------------------
bleeck@4 61 % find x positions of ALL local maxima, incl. zero!!
bleeck@4 62 max_x = find((values >= [0 values(1:end-1)]) & (values > [values(2:end) 0]));
bleeck@4 63 if isfield(params,'smooth_sigma')
bleeck@4 64 if (params.smooth_sigma~=0)
bleeck@4 65 % smoothing might have shifted the positions of maxima.
bleeck@4 66 % Therefore the maximum is the highest of the neighbours in
bleeck@4 67 % distance +- smooth_sigma
bleeck@4 68 for i=1:length(max_x)
bleeck@4 69 start = max_x(i)-params.smooth_sigma;
bleeck@4 70 if start<1
bleeck@4 71 start=1;
bleeck@4 72 end
bleeck@4 73 stop = max_x(i)+params.smooth_sigma;
bleeck@4 74 if stop>length(orig_values)
bleeck@4 75 stop=length(orig_values);
bleeck@4 76 end
bleeck@4 77 m = find(orig_values(start:stop) == max(orig_values(start:stop)));
bleeck@4 78 m=m(1);
bleeck@4 79 max_x(i)=start-1+m;
bleeck@4 80 end
bleeck@4 81 end
bleeck@4 82 end
bleeck@4 83 max_y = orig_values(max_x);
bleeck@4 84 orig_max_y = orig_values(max_x);
bleeck@4 85
bleeck@4 86 % ------------------- Find the local minima -----------------------------
bleeck@4 87 min_x = find((values < [inf values(1:end-1)]) & (values <= [values(2:end) inf]));
bleeck@4 88 min_y = values(min_x);
bleeck@4 89
bleeck@4 90
bleeck@4 91 % peakpos_x=zeros(1,length(max_x));
bleeck@4 92 peakpos_x=[];
bleeck@4 93 for i=1:length(max_x),
bleeck@4 94 % only take the highest peak
bleeck@4 95 my = [max_y==max(max_y)]; % find the highest peak
bleeck@4 96 % peakpos_x(i) = max_x(my); % x pos of highest peak
bleeck@4 97 peakpos_x = [peakpos_x max_x(my)];
bleeck@4 98 max_y = max_y([max_y<max(max_y)]); % del max value in y domain
bleeck@4 99 max_x = max_x([max_x ~= peakpos_x(end)]); % and in x domain
bleeck@4 100 end
bleeck@4 101 peakpos_y = orig_values(peakpos_x); % extract the y vector
bleeck@4 102
bleeck@4 103 % --------------- Dynamic Threshold ---------------------
bleeck@4 104 % works relativ to the mean
bleeck@4 105 if isfield(params,'dyn_thresh')
bleeck@4 106 if (params.dyn_thresh~=0)
bleeck@4 107 % dynamic thresholding
bleeck@4 108 m = mean(orig_values);
bleeck@4 109 dthr = params.dyn_thresh.*m;
bleeck@4 110 peakpos_x = peakpos_x([peakpos_y>=dthr]);
bleeck@4 111 peakpos_y = peakpos_y([peakpos_y>=dthr]);
bleeck@4 112 end
bleeck@4 113 end
bleeck@4 114
bleeck@4 115 maxima = cell(1, length(peakpos_x));
bleeck@4 116 % find the left end right minima that belong to a maximum
bleeck@4 117 for i=1:length(peakpos_x)
bleeck@4 118 maxima{i}.x = peakpos_x(i);
bleeck@4 119 maxima{i}.t = bin2time(sig_in, maxima{i}.x);
bleeck@4 120 maxima{i}.y = orig_values(peakpos_x(i));
bleeck@4 121
bleeck@4 122 % find left and right minimum for this maximum
bleeck@4 123 maxima{i}.left.x = max(min_x([min_x < maxima{i}.x]));
bleeck@4 124 if isempty(maxima{i}.left.x)
bleeck@4 125 maxima{i}.left.x = 1;
bleeck@4 126 maxima{i}.left.t = 0;
bleeck@4 127 maxima{i}.left.y = orig_values(maxima{i}.left.x);
bleeck@4 128 else
bleeck@4 129 maxima{i}.left.y = orig_values(maxima{i}.left.x);
bleeck@4 130 maxima{i}.left.t = bin2time(sig_in, maxima{i}.left.x);
bleeck@4 131 end
bleeck@4 132 maxima{i}.right.x = min(min_x([min_x > maxima{i}.x]));
bleeck@4 133 if isempty(maxima{i}.right.x)
bleeck@4 134 maxima{i}.right.x = length(orig_values);
bleeck@4 135 maxima{i}.right.t = 0;
bleeck@4 136 maxima{i}.right.y = orig_values(maxima{i}.right.x);
bleeck@4 137 else
bleeck@4 138 maxima{i}.right.y = orig_values(maxima{i}.right.x);
bleeck@4 139 maxima{i}.right.t = bin2time(sig_in, maxima{i}.right.x);
bleeck@4 140 end
bleeck@4 141 end
bleeck@4 142
bleeck@4 143
bleeck@4 144 out = maxima;
bleeck@4 145
bleeck@4 146