annotate 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
rev   line source
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;