bleeck@4
|
1 % function [pitchstrength, dominant_time] = find_pitches(profile, , a_priori, fqp_fq)
|
bleeck@4
|
2 %
|
bleeck@4
|
3 % To analyse the time interval profile of the auditory image
|
bleeck@4
|
4 %
|
bleeck@4
|
5 % INPUT VALUES:
|
bleeck@4
|
6 %
|
bleeck@4
|
7 % RETURN VALUE:
|
bleeck@4
|
8 %
|
bleeck@4
|
9
|
bleeck@4
|
10 % (c) 2011, University of Southampton
|
bleeck@4
|
11 % Maintained by Stefan Bleeck (bleeck@gmail.com)
|
bleeck@4
|
12 % download of current version is on the soundsoftware site:
|
bleeck@4
|
13 % http://code.soundsoftware.ac.uk/projects/aimmat
|
bleeck@4
|
14 % documentation and everything is on http://www.acousticscale.org
|
bleeck@4
|
15
|
bleeck@4
|
16 function result = find_pitches(profile,options)
|
bleeck@4
|
17
|
bleeck@4
|
18 plot_switch =0;
|
bleeck@4
|
19
|
bleeck@4
|
20 if nargin < 2
|
bleeck@4
|
21 options=[];
|
bleeck@4
|
22 end
|
bleeck@4
|
23 %
|
bleeck@4
|
24
|
bleeck@4
|
25 % peaks must be higher then this of the maximum to be recognised
|
bleeck@4
|
26 ps_threshold=0.1;
|
bleeck@4
|
27 heighttowidthminimum=0.3; % height of peak, where the width is measured
|
bleeck@4
|
28 octave_variability=0.35; % in percent, when the octave is acepted as such
|
bleeck@4
|
29
|
bleeck@4
|
30
|
bleeck@4
|
31
|
bleeck@4
|
32 % preliminary return values.
|
bleeck@4
|
33 result.final_pitchstrength=0;
|
bleeck@4
|
34 result.final_dominant_frequency=0;
|
bleeck@4
|
35 result.final_dominant_time=0;
|
bleeck@4
|
36 result.smoothed_signal=[];
|
bleeck@4
|
37 result.peaks = [];
|
bleeck@4
|
38
|
bleeck@4
|
39 % change the scaling to logarithm, before doing anything else:
|
bleeck@4
|
40 log_profile=logsigx(profile,0.001,0.035);
|
bleeck@4
|
41
|
bleeck@4
|
42
|
bleeck@4
|
43 peak_found=0;
|
bleeck@4
|
44 current_lowpass_frequency=500;
|
bleeck@4
|
45
|
bleeck@4
|
46 while ~peak_found
|
bleeck@4
|
47
|
bleeck@4
|
48 smooth_sig=lowpass(log_profile,current_lowpass_frequency);
|
bleeck@4
|
49 envpeaks = IPeakPicker(smooth_sig,0.01);
|
bleeck@4
|
50
|
bleeck@4
|
51 if isempty(envpeaks) % only, when there is no signal
|
bleeck@4
|
52 return
|
bleeck@4
|
53 end
|
bleeck@4
|
54
|
bleeck@4
|
55 % finde den peak mit der höchsten Pitschstrength
|
bleeck@4
|
56 for i=1:length(envpeaks) % construct all maxima
|
bleeck@4
|
57 where=bin2time(smooth_sig,envpeaks{i}.x);
|
bleeck@4
|
58 [dummy,height,breit,where_widths]=qvalue(smooth_sig,where,heighttowidthminimum);
|
bleeck@4
|
59 width=time2bin(smooth_sig,breit);
|
bleeck@4
|
60 if width>0
|
bleeck@4
|
61 envpeaks{i}.pitchstrength=height/width;
|
bleeck@4
|
62 else
|
bleeck@4
|
63 envpeaks{i}.pitchstrength=0;
|
bleeck@4
|
64 end
|
bleeck@4
|
65 envpeaks{i}.width=width;
|
bleeck@4
|
66 envpeaks{i}.where_widths=where_widths;
|
bleeck@4
|
67 envpeaks{i}.peak_base_height_y=height*(1-heighttowidthminimum);
|
bleeck@4
|
68 end
|
bleeck@4
|
69
|
bleeck@4
|
70 % sort all for the highest first!
|
bleeck@4
|
71 % envpeaks=sortstruct(envpeaks,'pitchstrength');
|
bleeck@4
|
72 envpeaks=sortstruct(envpeaks,'y');
|
bleeck@4
|
73
|
bleeck@4
|
74 if plot_switch
|
bleeck@4
|
75 figure(2134)
|
bleeck@4
|
76 clf
|
bleeck@4
|
77 hold on
|
bleeck@4
|
78 plot(log_profile,'b')
|
bleeck@4
|
79 plot(smooth_sig,'g')
|
bleeck@4
|
80 for i=1:length(envpeaks)
|
bleeck@4
|
81 time=envpeaks{i}.t;
|
bleeck@4
|
82 x=envpeaks{i}.x;
|
bleeck@4
|
83 y=envpeaks{i}.y;
|
bleeck@4
|
84 plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',2);
|
bleeck@4
|
85 time_left=envpeaks{i}.left.t;
|
bleeck@4
|
86 x_left=envpeaks{i}.left.x;
|
bleeck@4
|
87 y_left=envpeaks{i}.left.y;
|
bleeck@4
|
88 time_right=envpeaks{i}.right.t;
|
bleeck@4
|
89 x_right=envpeaks{i}.right.x;
|
bleeck@4
|
90 y_right=envpeaks{i}.right.y;
|
bleeck@4
|
91 plot(x_left,y_left,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
|
bleeck@4
|
92 plot(x_right,y_right,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
|
bleeck@4
|
93 end
|
bleeck@4
|
94 current_time=options.current_time*1000;
|
bleeck@4
|
95 y=get(gca,'ylim');
|
bleeck@4
|
96 y=y(2);
|
bleeck@4
|
97 text(700,y,sprintf('%3.0f ms',current_time),'verticalalignment','top');
|
bleeck@4
|
98
|
bleeck@4
|
99 for i=1:length(envpeaks)
|
bleeck@4
|
100 pitchstrength=envpeaks{i}.pitchstrength;
|
bleeck@4
|
101 if i <4
|
bleeck@4
|
102 line([envpeaks{i}.x envpeaks{i}.x],[envpeaks{i}.y envpeaks{i}.y*(1-heighttowidthminimum)],'Color','r');
|
bleeck@4
|
103 line([envpeaks{i}.where_widths(1) envpeaks{i}.where_widths(2)],[envpeaks{i}.y*(1-heighttowidthminimum) envpeaks{i}.y*(1-heighttowidthminimum)],'Color','r');
|
bleeck@4
|
104 x=envpeaks{i}.x;
|
bleeck@4
|
105 fre=envpeaks{i}.fre;
|
bleeck@4
|
106 y=envpeaks{i}.y;
|
bleeck@4
|
107 text(x,y*1.05,sprintf('%3.0fHz: %2.2f',fre,pitchstrength),'HorizontalAlignment','center');
|
bleeck@4
|
108 end
|
bleeck@4
|
109 end
|
bleeck@4
|
110 end
|
bleeck@4
|
111
|
bleeck@4
|
112 % kucke, ob sich das erste Maxima überlappt. Falls ja, nochmal
|
bleeck@4
|
113 % berechnen mit niedriger Lowpass frequenz
|
bleeck@4
|
114 nr_peaks=length(envpeaks);
|
bleeck@4
|
115 if nr_peaks==1
|
bleeck@4
|
116 peak_found=1;
|
bleeck@4
|
117 continue
|
bleeck@4
|
118 end
|
bleeck@4
|
119 xleft=envpeaks{1}.where_widths(1);
|
bleeck@4
|
120 xright=envpeaks{1}.where_widths(2);
|
bleeck@4
|
121 for i=2:nr_peaks %
|
bleeck@4
|
122 xnull=envpeaks{i}.x;
|
bleeck@4
|
123 if xnull < xleft && xnull > xright
|
bleeck@4
|
124 peak_found=0;
|
bleeck@4
|
125 current_lowpass_frequency=current_lowpass_frequency/2;
|
bleeck@4
|
126 if current_lowpass_frequency<62.5
|
bleeck@4
|
127 return
|
bleeck@4
|
128 end
|
bleeck@4
|
129 break
|
bleeck@4
|
130 end
|
bleeck@4
|
131 % wenn noch hier, dann ist alles ok
|
bleeck@4
|
132 peak_found=1;
|
bleeck@4
|
133 end
|
bleeck@4
|
134 end
|
bleeck@4
|
135
|
bleeck@4
|
136
|
bleeck@4
|
137 % reduce the peaks to the relevant ones:
|
bleeck@4
|
138 % through out all with pitchstrength smaller then threshold
|
bleeck@4
|
139 count=1;
|
bleeck@4
|
140 min_ps=ps_threshold*envpeaks{1}.pitchstrength;
|
bleeck@4
|
141 for i=1:length(envpeaks)
|
bleeck@4
|
142 if envpeaks{i}.pitchstrength>min_ps
|
bleeck@4
|
143 rpeaks{count}=envpeaks{i};
|
bleeck@4
|
144 count=count+1;
|
bleeck@4
|
145 end
|
bleeck@4
|
146 end
|
bleeck@4
|
147
|
bleeck@4
|
148
|
bleeck@4
|
149 % final result for the full set
|
bleeck@4
|
150 result.final_pitchstrength=rpeaks{1}.pitchstrength;
|
bleeck@4
|
151 result.final_dominant_frequency=rpeaks{1}.fre;
|
bleeck@4
|
152 result.final_dominant_time=rpeaks{1}.t;
|
bleeck@4
|
153 result.smoothed_signal=smooth_sig;
|
bleeck@4
|
154 result.peaks=rpeaks;
|
bleeck@4
|
155 % return
|
bleeck@4
|
156
|
bleeck@4
|
157 % Neuberechnung der Pitchstrength für peaks, die das Kriterium der
|
bleeck@4
|
158 % Höhe zu Breite nicht erfüllen
|
bleeck@4
|
159 for i=1:length(rpeaks) % construct all maxima
|
bleeck@4
|
160 where=bin2time(smooth_sig,rpeaks{i}.x);
|
bleeck@4
|
161 [dummy,height,breit,where_widths]=qvalue(smooth_sig,where,heighttowidthminimum);
|
bleeck@4
|
162 width=time2bin(smooth_sig,breit);
|
bleeck@4
|
163
|
bleeck@4
|
164 xleft=where_widths(2);
|
bleeck@4
|
165 xright=where_widths(1);
|
bleeck@4
|
166 left_peak=rpeaks{i}.left;
|
bleeck@4
|
167 right_peak=rpeaks{i}.right;
|
bleeck@4
|
168
|
bleeck@4
|
169
|
bleeck@4
|
170 xnull=rpeaks{i}.x;
|
bleeck@4
|
171 if xleft<left_peak.x || xright>right_peak.x
|
bleeck@4
|
172 t_xnull=bin2time(smooth_sig,xnull);
|
bleeck@4
|
173 [val,height,breit,widthvals,base_peak_y]=qvalue2(smooth_sig,t_xnull);
|
bleeck@4
|
174 width=time2bin(smooth_sig,breit);
|
bleeck@4
|
175 if width>0
|
bleeck@4
|
176 rpeaks{i}.pitchstrength=height/width;
|
bleeck@4
|
177 else
|
bleeck@4
|
178 rpeaks{i}.pitchstrength=0;
|
bleeck@4
|
179 end
|
bleeck@4
|
180 rpeaks{i}.where_widths=time2bin(smooth_sig,widthvals);
|
bleeck@4
|
181 rpeaks{i}.width=width;
|
bleeck@4
|
182 rpeaks{i}.peak_base_height_y=base_peak_y;
|
bleeck@4
|
183 end
|
bleeck@4
|
184 end
|
bleeck@4
|
185
|
bleeck@4
|
186 % sort again all for the highest first!
|
bleeck@4
|
187 % rpeaks=sortstruct(rpeaks,'pitchstrength');
|
bleeck@4
|
188
|
bleeck@4
|
189 % return
|
bleeck@4
|
190 %%%%%% look for octave relationships
|
bleeck@4
|
191 %
|
bleeck@4
|
192 %
|
bleeck@4
|
193 for i=1:length(rpeaks) % construct all maxima
|
bleeck@4
|
194 % look, if the octave of the pitch is also present.
|
bleeck@4
|
195 fre=rpeaks{i}.fre;
|
bleeck@4
|
196 has_octave=0;
|
bleeck@4
|
197 for j=1:length(rpeaks)
|
bleeck@4
|
198 oct_fre=rpeaks{j}.fre;
|
bleeck@4
|
199 % is the octave there?
|
bleeck@4
|
200 if oct_fre > (2-octave_variability)*fre && oct_fre < (2+octave_variability)*fre
|
bleeck@4
|
201 rpeaks{i}.has_octave=oct_fre;
|
bleeck@4
|
202 rpeaks{i}.octave_peak_nr=j;
|
bleeck@4
|
203
|
bleeck@4
|
204 % add the pss
|
bleeck@4
|
205 % rpeaks{j}.pitchstrength=rpeaks{i}.pitchstrength+rpeaks{j}.pitchstrength;
|
bleeck@4
|
206
|
bleeck@4
|
207 ps_real=rpeaks{j}.pitchstrength;
|
bleeck@4
|
208 ps_oct=rpeaks{i}.pitchstrength;
|
bleeck@4
|
209 hight_oct=rpeaks{j}.y;
|
bleeck@4
|
210 hight_real=rpeaks{i}.y;
|
bleeck@4
|
211
|
bleeck@4
|
212 % if ps_oct>ps_real && hight_oct > hight_real
|
bleeck@4
|
213 % rpeaks{i}.pitchstrength=ps_real-1; % artificially drop down
|
bleeck@4
|
214 % end
|
bleeck@4
|
215
|
bleeck@4
|
216 has_octave=1;
|
bleeck@4
|
217 break
|
bleeck@4
|
218 end
|
bleeck@4
|
219 if ~has_octave
|
bleeck@4
|
220 rpeaks{i}.has_octave=0;
|
bleeck@4
|
221 rpeaks{i}.octave_peak_nr=0;
|
bleeck@4
|
222 end
|
bleeck@4
|
223 end
|
bleeck@4
|
224 end
|
bleeck@4
|
225
|
bleeck@4
|
226 if plot_switch
|
bleeck@4
|
227 figure(2134)
|
bleeck@4
|
228 clf
|
bleeck@4
|
229 hold on
|
bleeck@4
|
230 plot(log_profile,'b')
|
bleeck@4
|
231 plot(smooth_sig,'g')
|
bleeck@4
|
232 for i=1:length(rpeaks)
|
bleeck@4
|
233 time=rpeaks{i}.t;
|
bleeck@4
|
234 x=rpeaks{i}.x;
|
bleeck@4
|
235 y=rpeaks{i}.y;
|
bleeck@4
|
236 plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',2);
|
bleeck@4
|
237 time_left=rpeaks{i}.left.t;
|
bleeck@4
|
238 x_left=rpeaks{i}.left.x;
|
bleeck@4
|
239 y_left=rpeaks{i}.left.y;
|
bleeck@4
|
240 time_right=rpeaks{i}.right.t;
|
bleeck@4
|
241 x_right=rpeaks{i}.right.x;
|
bleeck@4
|
242 y_right=rpeaks{i}.right.y;
|
bleeck@4
|
243 plot(x_left,y_left,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
|
bleeck@4
|
244 plot(x_right,y_right,'Marker','o','Markerfacecolor','r','MarkeredgeColor','r','MarkerSize',2);
|
bleeck@4
|
245 end
|
bleeck@4
|
246 current_time=options.current_time*1000;
|
bleeck@4
|
247 y=get(gca,'ylim');
|
bleeck@4
|
248 y=y(2);
|
bleeck@4
|
249 text(700,y,sprintf('%3.0f ms',current_time),'verticalalignment','top');
|
bleeck@4
|
250
|
bleeck@4
|
251 for i=1:length(rpeaks)
|
bleeck@4
|
252 pitchstrength=rpeaks{i}.pitchstrength;
|
bleeck@4
|
253 if i <10
|
bleeck@4
|
254 line([rpeaks{i}.x rpeaks{i}.x],[rpeaks{i}.y rpeaks{i}.peak_base_height_y],'Color','m');
|
bleeck@4
|
255 line([rpeaks{i}.where_widths(1) rpeaks{i}.where_widths(2)],[rpeaks{i}.peak_base_height_y rpeaks{i}.peak_base_height_y],'Color','m');
|
bleeck@4
|
256 x=rpeaks{i}.x;
|
bleeck@4
|
257 fre=rpeaks{i}.fre;
|
bleeck@4
|
258 y=rpeaks{i}.y;
|
bleeck@4
|
259 text(x,y*1.05,sprintf('%3.0fHz: %2.2f',fre,pitchstrength),'HorizontalAlignment','center');
|
bleeck@4
|
260 end
|
bleeck@4
|
261 end
|
bleeck@4
|
262 end
|
bleeck@4
|
263 if plot_switch==1
|
bleeck@4
|
264 for i=1:length(rpeaks)
|
bleeck@4
|
265 x=rpeaks{i}.x;
|
bleeck@4
|
266 y=rpeaks{i}.y;
|
bleeck@4
|
267 plot(x,y,'Marker','o','Markerfacecolor','g','MarkeredgeColor','g','MarkerSize',6);
|
bleeck@4
|
268
|
bleeck@4
|
269 % plot the octaves as green lines
|
bleeck@4
|
270 octave=rpeaks{i}.has_octave;
|
bleeck@4
|
271 fre=rpeaks{i}.fre;
|
bleeck@4
|
272 if octave>0
|
bleeck@4
|
273 oct_nr=rpeaks{i}.octave_peak_nr;
|
bleeck@4
|
274 oct_fre=rpeaks{oct_nr}.fre;
|
bleeck@4
|
275
|
bleeck@4
|
276 x=rpeaks{i}.x;
|
bleeck@4
|
277 oct_x=rpeaks{oct_nr}.x;
|
bleeck@4
|
278 y=rpeaks{i}.y;
|
bleeck@4
|
279 oct_y=rpeaks{oct_nr}.y;
|
bleeck@4
|
280 line([x oct_x],[y oct_y],'Color','g','LineStyle','--');
|
bleeck@4
|
281 end
|
bleeck@4
|
282 end
|
bleeck@4
|
283 end
|
bleeck@4
|
284
|
bleeck@4
|
285 % rpeaks=sortstruct(rpeaks,'pitchstrength');
|
bleeck@4
|
286 rpeaks=sortstruct(rpeaks,'y');
|
bleeck@4
|
287
|
bleeck@4
|
288 % final result for the full set
|
bleeck@4
|
289 result.final_pitchstrength=rpeaks{1}.pitchstrength;
|
bleeck@4
|
290 result.final_dominant_frequency=rpeaks{1}.fre;
|
bleeck@4
|
291 result.final_dominant_time=rpeaks{1}.t;
|
bleeck@4
|
292 result.smoothed_signal=smooth_sig;
|
bleeck@4
|
293 result.peaks=rpeaks;
|
bleeck@4
|
294
|
bleeck@4
|
295
|
bleeck@4
|
296
|
bleeck@4
|
297
|
bleeck@4
|
298 function fre=x2fre(sig,x)
|
bleeck@4
|
299 t_log = bin2time(sig,x);
|
bleeck@4
|
300 t=f2f(t_log,0,0.035,0.001,0.035,'linlog');
|
bleeck@4
|
301 fre=1/t;
|