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