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
|
bleeck@4
|
33 % ----- Other Parameters -----
|
bleeck@4
|
34 % Lowpass param for the higpassfilter
|
bleeck@4
|
35 LP_sigma_for_HP_filter = getnrpoints(sig_in)/7;
|
bleeck@4
|
36 LP_sigma_for_smooth = 3;
|
bleeck@4
|
37 % min width of a peak: upper_threshold+lower_thresh
|
bleeck@4
|
38 upper_thresh = 0.02*getnrpoints(sig_in);
|
bleeck@4
|
39 lower_thresh = 0.03*getnrpoints(sig_in);
|
bleeck@4
|
40
|
bleeck@4
|
41 % x is index or position in vector
|
bleeck@4
|
42 % y is value of the
|
bleeck@4
|
43 % t is the time domain wich is assigned to the x dimension
|
bleeck@4
|
44
|
bleeck@4
|
45 % the original values befor filtering
|
bleeck@4
|
46 orig_values = getdata(sig_in)';
|
bleeck@4
|
47
|
bleeck@4
|
48 if isfield(params,'smooth_sigma')
|
bleeck@4
|
49 if (params.smooth_sigma~=0)
|
bleeck@4
|
50 % smooth the curve to kill small side peaks
|
bleeck@4
|
51 sig_in = smooth(sig_in, params.smooth_sigma);
|
bleeck@4
|
52 end
|
bleeck@4
|
53 end
|
bleeck@4
|
54
|
bleeck@4
|
55 values=getdata(sig_in)';
|
bleeck@4
|
56
|
bleeck@4
|
57 % ------------------- Find the local maxima ------------------------------
|
bleeck@4
|
58 % find x positions of ALL local maxima, incl. zero!!
|
bleeck@4
|
59 max_x = find((values >= [0 values(1:end-1)]) & (values > [values(2:end) 0]));
|
bleeck@4
|
60 if isfield(params,'smooth_sigma')
|
bleeck@4
|
61 if (params.smooth_sigma~=0)
|
bleeck@4
|
62 % smoothing might have shifted the positions of maxima.
|
bleeck@4
|
63 % Therefore the maximum is the highest of the neighbours in
|
bleeck@4
|
64 % distance +- smooth_sigma
|
bleeck@4
|
65 for i=1:length(max_x)
|
bleeck@4
|
66 start = max_x(i)-params.smooth_sigma;
|
bleeck@4
|
67 if start<1
|
bleeck@4
|
68 start=1;
|
bleeck@4
|
69 end
|
bleeck@4
|
70 stop = max_x(i)+params.smooth_sigma;
|
bleeck@4
|
71 if stop>length(orig_values)
|
bleeck@4
|
72 stop=length(orig_values);
|
bleeck@4
|
73 end
|
bleeck@4
|
74 m = find(orig_values(start:stop) == max(orig_values(start:stop)));
|
bleeck@4
|
75 m=m(1);
|
bleeck@4
|
76 max_x(i)=start-1+m;
|
bleeck@4
|
77 end
|
bleeck@4
|
78 end
|
bleeck@4
|
79 end
|
bleeck@4
|
80 max_y = orig_values(max_x);
|
bleeck@4
|
81 orig_max_y = orig_values(max_x);
|
bleeck@4
|
82
|
bleeck@4
|
83 % ------------------- Find the local minima -----------------------------
|
bleeck@4
|
84 min_x = find((values < [inf values(1:end-1)]) & (values <= [values(2:end) inf]));
|
bleeck@4
|
85 min_y = values(min_x);
|
bleeck@4
|
86
|
bleeck@4
|
87
|
bleeck@4
|
88 % peakpos_x=zeros(1,length(max_x));
|
bleeck@4
|
89 peakpos_x=[];
|
bleeck@4
|
90 for i=1:length(max_x),
|
bleeck@4
|
91 % only take the highest peak
|
bleeck@4
|
92 my = [max_y==max(max_y)]; % find the highest peak
|
bleeck@4
|
93 % peakpos_x(i) = max_x(my); % x pos of highest peak
|
bleeck@4
|
94 peakpos_x = [peakpos_x max_x(my)];
|
bleeck@4
|
95 max_y = max_y([max_y<max(max_y)]); % del max value in y domain
|
bleeck@4
|
96 max_x = max_x([max_x ~= peakpos_x(end)]); % and in x domain
|
bleeck@4
|
97 end
|
bleeck@4
|
98 peakpos_y = orig_values(peakpos_x); % extract the y vector
|
bleeck@4
|
99
|
bleeck@4
|
100 % --------------- Dynamic Threshold ---------------------
|
bleeck@4
|
101 % works relativ to the mean
|
bleeck@4
|
102 if isfield(params,'dyn_thresh')
|
bleeck@4
|
103 if (params.dyn_thresh~=0)
|
bleeck@4
|
104 % dynamic thresholding
|
bleeck@4
|
105 m = mean(orig_values);
|
bleeck@4
|
106 dthr = params.dyn_thresh.*m;
|
bleeck@4
|
107 peakpos_x = peakpos_x([peakpos_y>=dthr]);
|
bleeck@4
|
108 peakpos_y = peakpos_y([peakpos_y>=dthr]);
|
bleeck@4
|
109 end
|
bleeck@4
|
110 end
|
bleeck@4
|
111
|
bleeck@4
|
112 maxima = cell(1, length(peakpos_x));
|
bleeck@4
|
113 % find the left end right minima that belong to a maximum
|
bleeck@4
|
114 for i=1:length(peakpos_x)
|
bleeck@4
|
115 maxima{i}.x = peakpos_x(i);
|
bleeck@4
|
116 maxima{i}.t = bin2time(sig_in, maxima{i}.x);
|
bleeck@4
|
117 maxima{i}.y = orig_values(peakpos_x(i));
|
bleeck@4
|
118
|
bleeck@4
|
119 % find left and right minimum for this maximum
|
bleeck@4
|
120 maxima{i}.left.x = max(min_x([min_x < maxima{i}.x]));
|
bleeck@4
|
121 if isempty(maxima{i}.left.x)
|
bleeck@4
|
122 maxima{i}.left.x = 1;
|
bleeck@4
|
123 maxima{i}.left.t = 0;
|
bleeck@4
|
124 maxima{i}.left.y = orig_values(maxima{i}.left.x);
|
bleeck@4
|
125 else
|
bleeck@4
|
126 maxima{i}.left.y = orig_values(maxima{i}.left.x);
|
bleeck@4
|
127 maxima{i}.left.t = bin2time(sig_in, maxima{i}.left.x);
|
bleeck@4
|
128 end
|
bleeck@4
|
129 maxima{i}.right.x = min(min_x([min_x > maxima{i}.x]));
|
bleeck@4
|
130 if isempty(maxima{i}.right.x)
|
bleeck@4
|
131 maxima{i}.right.x = length(orig_values);
|
bleeck@4
|
132 maxima{i}.right.t = 0;
|
bleeck@4
|
133 maxima{i}.right.y = orig_values(maxima{i}.right.x);
|
bleeck@4
|
134 else
|
bleeck@4
|
135 maxima{i}.right.y = orig_values(maxima{i}.right.x);
|
bleeck@4
|
136 maxima{i}.right.t = bin2time(sig_in, maxima{i}.right.x);
|
bleeck@4
|
137 end
|
bleeck@4
|
138 end
|
bleeck@4
|
139
|
bleeck@4
|
140
|
bleeck@4
|
141 out = maxima;
|
bleeck@4
|
142
|
bleeck@4
|
143
|