annotate aim-mat/tools/adaptivthreshold.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 20ada0af3d7d
children
rev   line source
tomwalters@0 1 % tool
tomwalters@0 2 %
tomwalters@0 3 % INPUT VALUES:
tomwalters@0 4 %
tomwalters@0 5 % RETURN VALUE:
tomwalters@0 6 %
tomwalters@0 7 %
bleeck@3 8 % (c) 2011, University of Southampton
bleeck@3 9 % Maintained by Stefan Bleeck (bleeck@gmail.com)
bleeck@3 10 % download of current version is on the soundsoftware site:
bleeck@3 11 % http://code.soundsoftware.ac.uk/projects/aimmat
bleeck@3 12 % documentation and everything is on http://www.acousticscale.org
bleeck@3 13
tomwalters@0 14
tomwalters@0 15 function [newsig,strobe_points,threshold]=adaptivthreshold(sig,options)
tomwalters@0 16
tomwalters@0 17 if nargin < 2
tomwalters@0 18 options=[];
tomwalters@0 19 end
tomwalters@0 20
tomwalters@0 21 % the way, in which the strobes are calculated
tomwalters@0 22 if isfield(options,'strobe_decay_time')
tomwalters@0 23 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 24 else
tomwalters@0 25 strobe_decay_time=0.04;
tomwalters@0 26 end
tomwalters@0 27
tomwalters@0 28 % the time constant of the strobe decay
tomwalters@0 29 if isfield(options,'strobe_decay_time')
tomwalters@0 30 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 31 else
tomwalters@0 32 strobe_decay_time=0.04;
tomwalters@0 33 end
tomwalters@0 34
tomwalters@0 35 % the timeout, after that time a strobe must occure
tomwalters@0 36 if isfield(options,'timeout')
tomwalters@0 37 timeout=options.timeout;
tomwalters@0 38 else
tomwalters@0 39 strobe_decay_time=0.01;
tomwalters@0 40 end
tomwalters@0 41
tomwalters@0 42 % the strobe lag, ie the time that is waited for the next strobe to occure
tomwalters@0 43 if isfield(options,'strobe_lag')
tomwalters@0 44 strobe_lag=options.strobe_lag;
tomwalters@0 45 else
tomwalters@0 46 strobe_lag=0.005;
tomwalters@0 47 end
tomwalters@0 48
tomwalters@0 49 % the threshold of a strobe
tomwalters@0 50 if isfield(options,'threshold')
tomwalters@0 51 threshold=options.threshold;
tomwalters@0 52 else
tomwalters@0 53 threshold=0.04;
tomwalters@0 54 end
tomwalters@0 55
tomwalters@0 56 % if we want to start with a different threshold
tomwalters@0 57 if isfield(options,'startingthreshold')
tomwalters@0 58 current_threshold=options.startingthreshold;
tomwalters@0 59 else
tomwalters@0 60 current_threshold=0;
tomwalters@0 61 end
tomwalters@0 62
tomwalters@0 63 % if some graphic should be displayed during run
tomwalters@0 64 if isfield(options,'grafix')
tomwalters@0 65 grafix=options.grafix;
tomwalters@0 66 else
tomwalters@0 67 grafix=0; %
tomwalters@0 68 end
tomwalters@0 69
tomwalters@0 70 % % if the result shell be filtered by this lowpass filter:
tomwalters@0 71 % if isfield(options,'lowpass')
tomwalters@0 72 % lowpassvalue=options.lowpass;
tomwalters@0 73 % else
tomwalters@0 74 % lowpassvalue=-1; %
tomwalters@0 75 % end
tomwalters@0 76
tomwalters@0 77 sr=getsr(sig);
tomwalters@0 78 newsig=sig;
tomwalters@0 79 newsig=setname(newsig,sprintf('adaptive threshold of %s',getname(sig)));
tomwalters@0 80 % newvals=getvalues(sig);
tomwalters@0 81 threshold=sig;
tomwalters@0 82 tresval=getvalues(sig);
tomwalters@0 83
tomwalters@0 84
tomwalters@0 85 sigvals=getvalues(sig);
tomwalters@0 86 options.current_threshold=current_threshold;
tomwalters@0 87 options.sr=sr;
tomwalters@0 88
tomwalters@0 89 switch options.strobe_criterion
tomwalters@0 90 case 'parabola'
tomwalters@0 91 [strobe_points,tresval,newvals]=doadaptivethresholdparabola(sigvals,options);
tomwalters@0 92 case 'threshold'
tomwalters@0 93 case 'peak'
tomwalters@0 94 [strobe_points,tresval,newvals]=doadaptivethresholdpeak(sigvals,options);
tomwalters@0 95 case 'peak_shadow+'
tomwalters@0 96 [strobe_points,tresval,newvals]=doadaptivethresholdpeakshadowplus(sigvals,options);
tomwalters@0 97 case 'peak_shadow-'
tomwalters@0 98 case 'delta_gamma'
tomwalters@0 99 case 'adaptive'
tomwalters@0 100 [strobe_points,tresval,newvals]=doadaptivethresholdadaptive(sigvals,options);
tomwalters@0 101 case 'bunt'
tomwalters@0 102 [strobe_points,tresval,newvals]=doadaptivethresholdbunt(sigvals,options);
tomwalters@0 103 end
tomwalters@0 104
tomwalters@0 105 strobe_points=bin2time(sig,strobe_points);
tomwalters@0 106
tomwalters@0 107 newsig=setvalues(newsig,newvals);
tomwalters@0 108 threshold=setvalues(threshold,tresval);
tomwalters@0 109
tomwalters@0 110 % % do a low pass filtering of the result to smooth it
tomwalters@0 111 % if lowpassvalue > -1
tomwalters@0 112 % if lowpassvalue > 2000
tomwalters@0 113 % lowpassvalue=2000;
tomwalters@0 114 % end
tomwalters@0 115 % newsig=lowpass(newsig,lowpassvalue);
tomwalters@0 116 % newsig=halfwayrectify(newsig);
tomwalters@0 117 % end
tomwalters@0 118
tomwalters@0 119
tomwalters@0 120 if grafix
tomwalters@0 121 clf
tomwalters@0 122 plot(sig); hold on
tomwalters@0 123 ax=axis;
tomwalters@0 124 plot(newsig,'r');
tomwalters@0 125 plot(threshold,'g');
tomwalters@0 126 axis(ax);
tomwalters@0 127 end
tomwalters@0 128 return
tomwalters@0 129
tomwalters@0 130
tomwalters@0 131 function [strobe_points,tresval,newvals]=doadaptivethresholdparabola(sigvals,options)
tomwalters@0 132 % the threshold is calculated relativ to the hight of the last strobe
tomwalters@0 133 % the sample rate is needed for the calculation of the next thresholds
tomwalters@0 134 % for time_constant_alpha this is a linear decreasing function that goes
tomwalters@0 135 % from the maximum value to 0 in the time_constant
tomwalters@0 136
tomwalters@0 137 current_threshold=options.current_threshold;
tomwalters@0 138 sr=options.sr;
tomwalters@0 139 last_strobe=-inf;
tomwalters@0 140
tomwalters@0 141 tresval=zeros(size(sigvals));
tomwalters@0 142 newvals=zeros(size(sigvals));
tomwalters@0 143 nr=length(sigvals);
tomwalters@0 144 strobe_points=zeros(100,1);
tomwalters@0 145
tomwalters@0 146 %when the last strobe occured
tomwalters@0 147 % last_strobe=-inf;
tomwalters@0 148 last_threshold_value=0;
tomwalters@0 149
tomwalters@0 150 % copy options to save time
tomwalters@0 151 h=options.parabel_heigth;
tomwalters@0 152 w=options.parabel_width;
tomwalters@0 153 % w=options.parabel_width_in_cycles*1/options.current_cf;
tomwalters@0 154 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 155
tomwalters@0 156 counter=1;
tomwalters@0 157 for ii=1:nr
tomwalters@0 158 current_val=sigvals(ii);
tomwalters@0 159 current_time=ii/sr;
tomwalters@0 160
tomwalters@0 161 if current_val>current_threshold
tomwalters@0 162 new_val=current_val-current_threshold;
tomwalters@0 163 current_threshold=current_val;
tomwalters@0 164 strobe_points(counter)=ii;
tomwalters@0 165 counter=counter+1;
tomwalters@0 166 last_strobe=ii;
tomwalters@0 167 last_threshold_value=current_threshold;
tomwalters@0 168 else
tomwalters@0 169 new_val=0;
tomwalters@0 170 end
tomwalters@0 171 tresval(ii)=current_threshold;
tomwalters@0 172
tomwalters@0 173 time_since_last_strobe=(ii-last_strobe)/sr;
tomwalters@0 174 if time_since_last_strobe > w % linear falling threshold
tomwalters@0 175 const_decay=last_threshold_value/sr/strobe_decay_time;
tomwalters@0 176 current_threshold=current_threshold-const_decay;
tomwalters@0 177 current_threshold=max(0,current_threshold);
tomwalters@0 178 else % parabel for the first time y=a(x+b)^2+c
tomwalters@0 179 a=4*(1-h)/(w*w);
tomwalters@0 180 b=-w/2;
tomwalters@0 181 c=h;
tomwalters@0 182 factor=a*(time_since_last_strobe + b) ^2+c;
tomwalters@0 183 current_threshold=last_threshold_value*factor;
tomwalters@0 184 end
tomwalters@0 185
tomwalters@0 186 current_threshold=max(0,current_threshold); % cant be smaller then 0
tomwalters@0 187
tomwalters@0 188 newvals(ii)=new_val;
tomwalters@0 189 end
tomwalters@0 190
tomwalters@0 191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 192 function [strobe_points,tresval,newvals]=doadaptivethresholdpeak(sigvals,options)
tomwalters@0 193 % finds every single local maximum
tomwalters@0 194 sr=options.sr;
tomwalters@0 195 tresval=zeros(size(sigvals));
tomwalters@0 196 newvals=zeros(size(sigvals));
tomwalters@0 197 strobe_points=zeros(100,1);
tomwalters@0 198 sig=signal(sigvals);
tomwalters@0 199 sig=setsr(sig,sr);
tomwalters@0 200 [t,h]=getlocalmaxima(sig);
tomwalters@0 201 strobe_points=t*sr;
tomwalters@0 202
tomwalters@0 203
tomwalters@0 204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 205 function [strobe_points,tresval,newvals]=doadaptivethresholdpeakshadowplus(sigvals,options)
tomwalters@0 206 % finds every single peak and starts from that an falling threshold
tomwalters@0 207
tomwalters@0 208 current_threshold=options.current_threshold;
tomwalters@0 209 sr=options.sr;
tomwalters@0 210 tresval=zeros(size(sigvals));
tomwalters@0 211 newvals=zeros(size(sigvals));
tomwalters@0 212 nr=length(sigvals);
tomwalters@0 213 strobe_points=zeros(100,1);
tomwalters@0 214 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 215 last_strobe=-inf;
tomwalters@0 216 counter=1;
tomwalters@0 217 last_threshold_value=0;
tomwalters@0 218
tomwalters@0 219 for ii=2:nr-1
tomwalters@0 220 current_val=sigvals(ii);
tomwalters@0 221 current_time=ii/sr;
tomwalters@0 222
tomwalters@0 223 if current_val>current_threshold
tomwalters@0 224 if sigvals(ii) > sigvals(ii-1) && sigvals(ii) > sigvals(ii+1)
tomwalters@0 225 new_val=current_val-current_threshold;
tomwalters@0 226 current_threshold=current_val;
tomwalters@0 227 strobe_points(counter)=ii;
tomwalters@0 228 counter=counter+1;
tomwalters@0 229 last_strobe=ii;
tomwalters@0 230 last_threshold_value=current_threshold;
tomwalters@0 231 end
tomwalters@0 232 end
tomwalters@0 233 const_decay=last_threshold_value/sr/strobe_decay_time;
tomwalters@0 234 current_threshold=current_threshold-const_decay;
tomwalters@0 235 current_threshold=max(0,current_threshold);
tomwalters@0 236 tresval(ii)=current_threshold;
tomwalters@0 237 end
tomwalters@0 238
tomwalters@0 239
tomwalters@0 240 function [strobe_points,tresval,newvals]=doadaptivethresholdadaptive(sigvals,options)
tomwalters@0 241 % the threshold is calculated relativ to the hight of the last strobe
tomwalters@0 242 % the sample rate is needed for the calculation of the next thresholds
tomwalters@0 243 % for time_constant_alpha this is a linear decreasing function that goes
tomwalters@0 244 % from the maximum value to 0 in the time_constant
tomwalters@0 245
tomwalters@0 246 current_threshold=options.current_threshold;
tomwalters@0 247 sr=options.sr;
tomwalters@0 248 last_strobe=-inf;
tomwalters@0 249
tomwalters@0 250 tresval=zeros(size(sigvals));
tomwalters@0 251 newvals=zeros(size(sigvals));
tomwalters@0 252 nr=length(sigvals);
tomwalters@0 253 strobe_points=zeros(100,1);
tomwalters@0 254
tomwalters@0 255 %when the last strobe occured
tomwalters@0 256 % last_strobe=-inf;
tomwalters@0 257 last_threshold_value=0;
tomwalters@0 258
tomwalters@0 259 % copy options to save time
tomwalters@0 260 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 261
tomwalters@0 262 bunt=0.5;
tomwalters@0 263
tomwalters@0 264 % decay_time=options.strobe_decay_time;
tomwalters@0 265 % threshold_decay_constant=power(0.5,1./(options.strobe_decay_time*sr));
tomwalters@0 266
tomwalters@0 267 slope_coefficient=options.slope_coefficient;
tomwalters@0 268 slope_coefficient=0.0005;
tomwalters@0 269 minoffset=0.2;
tomwalters@0 270
tomwalters@0 271 threshold_decay_offset=-1/(options.strobe_decay_time*sr);
tomwalters@0 272 default_threshold_decay_offset=threshold_decay_offset;
tomwalters@0 273
tomwalters@0 274 counter=1;
tomwalters@0 275 for ii=1:nr
tomwalters@0 276 current_val=sigvals(ii);
tomwalters@0 277 current_time=ii/sr;
tomwalters@0 278
tomwalters@0 279 if current_val>current_threshold
tomwalters@0 280 new_val=current_val-current_threshold;
tomwalters@0 281 current_threshold=current_val;
tomwalters@0 282 strobe_points(counter)=ii;
tomwalters@0 283 counter=counter+1;
tomwalters@0 284 time_offset=ii-last_strobe; % time since last strobe
tomwalters@0 285 last_strobe=ii;
tomwalters@0 286
tomwalters@0 287 amplitude_offset=current_threshold-last_threshold_value;
tomwalters@0 288
tomwalters@0 289 last_threshold_value=current_threshold;
tomwalters@0 290
tomwalters@0 291 current_bunt=0;
tomwalters@0 292 % if amplitude_offset>0
tomwalters@0 293 % current_bunt=amplitude_offset/1;
tomwalters@0 294 % else
tomwalters@0 295 % current_bunt=0;
tomwalters@0 296 % end
tomwalters@0 297 current_threshold=current_threshold+current_bunt+minoffset;
tomwalters@0 298
tomwalters@0 299 offset=amplitude_offset/time_offset*slope_coefficient;
tomwalters@0 300
tomwalters@0 301 threshold_decay_offset=threshold_decay_offset+offset;
tomwalters@0 302 % threshold_decay_constant=power(0.5,1./(decay_time*sr));
tomwalters@0 303 else
tomwalters@0 304 new_val=0;
tomwalters@0 305 end
tomwalters@0 306 tresval(ii)=current_threshold;
tomwalters@0 307 time_since_last_strobe=(ii-last_strobe)/sr;
tomwalters@0 308
tomwalters@0 309
tomwalters@0 310 % current_threshold=current_threshold*threshold_decay_constant;
tomwalters@0 311 current_threshold=current_threshold+threshold_decay_offset;
tomwalters@0 312 current_threshold=max(current_threshold,0);
tomwalters@0 313
tomwalters@0 314 if time_since_last_strobe>0.035
tomwalters@0 315 current_threshold=0;
tomwalters@0 316 threshold_decay_offset=default_threshold_decay_offset;
tomwalters@0 317 end
tomwalters@0 318
tomwalters@0 319 newvals(ii)=new_val;
tomwalters@0 320 end
tomwalters@0 321
tomwalters@0 322
tomwalters@0 323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 324 %%%% BUNT
tomwalters@0 325 function [strobe_points,tresval,newvals]=doadaptivethresholdbunt(sigvals,options)
tomwalters@0 326 % the bunt is relative to the last peak hight
tomwalters@0 327
tomwalters@0 328 current_threshold=options.current_threshold;
tomwalters@0 329 sr=options.sr;
tomwalters@0 330 last_strobe=-inf;
tomwalters@0 331
tomwalters@0 332 tresval=zeros(size(sigvals));
tomwalters@0 333 newvals=zeros(size(sigvals));
tomwalters@0 334 nr=length(sigvals);
tomwalters@0 335 strobe_points=zeros(100,1);
tomwalters@0 336
tomwalters@0 337 %when the last strobe occured
tomwalters@0 338 last_strobe_time=-inf;
tomwalters@0 339 last_threshold_value=0;
tomwalters@0 340
tomwalters@0 341 % copy options to save time
tomwalters@0 342 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 343
tomwalters@0 344 % wait that many cycles to confirm a strobe
tomwalters@0 345 wait_time=options.wait_cycles/options.cf;
tomwalters@0 346
tomwalters@0 347 % if waited for too long, then strobe anyhow after some passed candidates:
tomwalters@0 348 wait_candidate_max=options.nr_strobe_candidates;
tomwalters@0 349 current_jumped_candidates=1;
tomwalters@0 350
tomwalters@0 351
tomwalters@0 352 bunt=options.bunt;
tomwalters@0 353
tomwalters@0 354 strobe_decay_time=options.strobe_decay_time;
tomwalters@0 355 last_val=sigvals(1);
tomwalters@0 356
tomwalters@0 357 counter=1;
tomwalters@0 358 for ii=2:nr-1
tomwalters@0 359 current_val=sigvals(ii);
tomwalters@0 360 next_val=sigvals(ii+1);
tomwalters@0 361 current_time=ii/sr;
tomwalters@0 362 if current_val>=current_threshold % above threshold -> criterium for strobe
tomwalters@0 363 current_threshold=current_val;
tomwalters@0 364 if current_val > last_val && current_val > next_val % only strobe on local maxima
tomwalters@0 365
tomwalters@0 366 % so far its a candidate, but is it a real strobe?
tomwalters@0 367 % look if there was a strobe in the past, that is deleted
tomwalters@0 368 if (counter>1 && current_time-strobe_time(counter-1)<wait_time) %&& current_threshold >last_threshold_value
tomwalters@0 369 % if its too long in the past, fire anyway
tomwalters@0 370 if current_jumped_candidates > wait_candidate_max
tomwalters@0 371 current_jumped_candidates=1; % reset counter
tomwalters@0 372 else
tomwalters@0 373 current_jumped_candidates=current_jumped_candidates+1;
tomwalters@0 374 counter=counter-1; % delete the last one
tomwalters@0 375 end
tomwalters@0 376 else
tomwalters@0 377 current_jumped_candidates=current_jumped_candidates+1;
tomwalters@0 378 end
tomwalters@0 379
tomwalters@0 380
tomwalters@0 381 % take this one as a new one
tomwalters@0 382 strobe_points(counter)=ii;
tomwalters@0 383 strobe_time(counter)=ii/sr;
tomwalters@0 384 counter=counter+1; % strobecounter
tomwalters@0 385 current_threshold=current_threshold*options.bunt; %increase threshold
tomwalters@0 386
tomwalters@0 387 last_strobe_time=ii/sr; % anyhow, its a candidate
tomwalters@0 388 last_threshold_value=current_threshold;
tomwalters@0 389
tomwalters@0 390 end
tomwalters@0 391 end
tomwalters@0 392 tresval(ii)=current_threshold;
tomwalters@0 393
tomwalters@0 394 const_decay=last_threshold_value/sr/strobe_decay_time;
tomwalters@0 395 current_threshold=current_threshold-const_decay;
tomwalters@0 396
tomwalters@0 397 current_threshold=max(current_threshold,0);
tomwalters@0 398 last_val=current_val;
tomwalters@0 399 end
tomwalters@0 400