annotate toolboxes/MIRtoolbox1.3.2/MIRToolbox/@mirautocor/mirautocor.m @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function varargout = mirautocor(orig,varargin)
Daniel@0 2 % a = mirautocor(x) computes the autocorrelation function related to x.
Daniel@0 3 % Optional parameters:
Daniel@0 4 % mirautocor(...,'Min',mi) indicates the lowest delay taken into
Daniel@0 5 % consideration. The unit can be precised:
Daniel@0 6 % mirautocor(...,'Min',mi,'s') (default unit)
Daniel@0 7 % mirautocor(...,'Min',mi,'Hz')
Daniel@0 8 % Default value: 0 s.
Daniel@0 9 % mirautocor(...,'Max',ma) indicates the highest delay taken into
Daniel@0 10 % consideration. The unit can be specified as for 'Min'.
Daniel@0 11 % Default value:
Daniel@0 12 % if x is a signal, the highest delay is 0.05 s
Daniel@0 13 % (corresponding to a minimum frequency of 20 Hz).
Daniel@0 14 % if x is an envelope, the highest delay is 2 s.
Daniel@0 15 % mirautocor(...,'Resonance',r) multiplies the autocorrelation function
Daniel@0 16 % with a resonance curve:
Daniel@0 17 % Possible values:
Daniel@0 18 % 'Toiviainen' from (Toiviainen & Snyder, 2003)
Daniel@0 19 % 'vanNoorden' from (van Noorden & Moelants, 2001)
Daniel@0 20 % mirautocor(...,'Center',c) assigns the center value of the
Daniel@0 21 % resonance curve, in seconds.
Daniel@0 22 % Works mainly with 'Toiviainen' option.
Daniel@0 23 % Default value: c = 0.5
Daniel@0 24 % mirautocor(...,'Enhanced',a) reduces the effect of subharmonics.
Daniel@0 25 % The original autocorrelation function is half-wave rectified,
Daniel@0 26 % time-scaled by the factor a (which can be a factor list as
Daniel@0 27 % well), and substracted from the original clipped function.
Daniel@0 28 % (Tolonen & Karjalainen)
Daniel@0 29 % If the 'Enhanced' option is not followed by any value,
Daniel@0 30 % default value is a = 2:10
Daniel@0 31 % mirautocor(...,'Halfwave') performs a half-wave rectification on the
Daniel@0 32 % result.
Daniel@0 33 % mirautocor(...,'Freq') represents the autocorrelation function in the
Daniel@0 34 % frequency domain.
Daniel@0 35 % mirautocor(...,'NormalWindow',w): applies a window to the input
Daniel@0 36 % signal and divides the autocorrelation by the autocorrelation of
Daniel@0 37 % that window (Boersma 1993).
Daniel@0 38 % Possible values: any windowing function proposed in the Signal
Daniel@0 39 % Processing Toolbox (help window) plus 'rectangle' (no
Daniel@0 40 % windowing)
Daniel@0 41 % Default value: w = 'hanning'
Daniel@0 42 % mirautocor(...,'NormalWindow',0): toggles off this normalization
Daniel@0 43 % (which is on by default).
Daniel@0 44 % All the parameters described previously can be applied to an
Daniel@0 45 % autocorrelation function itself, in order to arrange the results
Daniel@0 46 % after the actual computation of the autocorrelation computations.
Daniel@0 47 % For instance: a = mirautocor(a,'Resonance','Enhanced')
Daniel@0 48 % Other optional parameter:
Daniel@0 49 % mirautocor(...,'Compres',k) computes the autocorrelation in the
Daniel@0 50 % frequency domain and includes a magnitude compression of the
Daniel@0 51 % spectral representation. A normal autocorrelation corresponds
Daniel@0 52 % to the value k=2, but values lower than 2 are suggested by
Daniel@0 53 % (Tolonen & Karjalainen, 2000).
Daniel@0 54 % Default value: k = 0.67
Daniel@0 55 % mirautocor(...,'Normal',n) or simply mirautocor(...,n) specifies
Daniel@0 56 % the normalization strategy. Accepted values are 'biased',
Daniel@0 57 % 'unbiased', 'coeff' (default value) and 'none'.
Daniel@0 58 % See help xcorr for an explanation.
Daniel@0 59
Daniel@0 60 min.key = 'Min';
Daniel@0 61 min.type = 'Integer';
Daniel@0 62 min.unit = {'s','Hz'};
Daniel@0 63 if isamir(orig,'mirspectrum')
Daniel@0 64 min.defaultunit = 'Hz';
Daniel@0 65 else
Daniel@0 66 min.defaultunit = 's';
Daniel@0 67 end
Daniel@0 68 min.default = 0;
Daniel@0 69 min.opposite = 'max';
Daniel@0 70 option.min = min;
Daniel@0 71
Daniel@0 72 max.key = 'Max';
Daniel@0 73 max.type = 'Integer';
Daniel@0 74 max.unit = {'s','Hz'};
Daniel@0 75 if isamir(orig,'mirspectrum')
Daniel@0 76 max.defaultunit = 'Hz';
Daniel@0 77 else
Daniel@0 78 max.defaultunit = 's';
Daniel@0 79 end
Daniel@0 80 if isamir(orig,'mirenvelope') || isamir(orig,'mirdiffenvelope')
Daniel@0 81 max.default = 2; % for envelopes, longest period: 2 seconds.
Daniel@0 82 elseif isamir(orig,'miraudio') || ischar(orig) % for audio signal,lowest frequency: 20 Hz.
Daniel@0 83 max.default = 1/20;
Daniel@0 84 else
Daniel@0 85 max.default = Inf;
Daniel@0 86 end
Daniel@0 87 max.opposite = 'min';
Daniel@0 88 option.max = max;
Daniel@0 89
Daniel@0 90 scaleoptbw.key = 'Normal'; %'Normal' keyword optional
Daniel@0 91 scaleoptbw.key = 'Boolean';
Daniel@0 92 option.scaleoptbw = scaleoptbw;
Daniel@0 93 scaleopt.type = 'String';
Daniel@0 94 scaleopt.choice = {'biased','unbiased','coeff','none'};
Daniel@0 95 scaleopt.default = 'coeff';
Daniel@0 96 option.scaleopt = scaleopt;
Daniel@0 97
Daniel@0 98 gener.key = {'Generalized','Compres'};
Daniel@0 99 gener.type = 'Integer';
Daniel@0 100 gener.default = 2;
Daniel@0 101 gener.keydefault = .67;
Daniel@0 102 option.gener = gener;
Daniel@0 103
Daniel@0 104 ni.key = 'NormalInput'; %% Normalize before frame or chunk??
Daniel@0 105 ni.type = 'Boolean';
Daniel@0 106 ni.default = 0;
Daniel@0 107 option.ni = ni;
Daniel@0 108
Daniel@0 109 reso.key = 'Resonance';
Daniel@0 110 reso.type = 'String';
Daniel@0 111 reso.choice = {'ToiviainenSnyder','Toiviainen','vanNoorden','no','off',0};
Daniel@0 112 reso.keydefault = 'Toiviainen';
Daniel@0 113 reso.when = 'After';
Daniel@0 114 reso.default = 0;
Daniel@0 115 option.reso = reso;
Daniel@0 116
Daniel@0 117 resocenter.key = {'Center','Centre'};
Daniel@0 118 resocenter.type = 'Integer';
Daniel@0 119 resocenter.when = 'After';
Daniel@0 120 option.resocenter = resocenter;
Daniel@0 121
Daniel@0 122 h.key = 'Halfwave';
Daniel@0 123 h.type = 'Boolean';
Daniel@0 124 h.when = 'After';
Daniel@0 125 h.default = 0;
Daniel@0 126 option.h = h;
Daniel@0 127
Daniel@0 128 e.key = 'Enhanced';
Daniel@0 129 e.type = 'Integers';
Daniel@0 130 e.default = [];
Daniel@0 131 e.keydefault = 2:10;
Daniel@0 132 e.when = 'After';
Daniel@0 133 option.e = e;
Daniel@0 134
Daniel@0 135 fr.key = 'Freq';
Daniel@0 136 fr.type = 'Boolean';
Daniel@0 137 fr.default = 0;
Daniel@0 138 fr.when = 'After';
Daniel@0 139 option.fr = fr;
Daniel@0 140
Daniel@0 141 nw.key = 'NormalWindow';
Daniel@0 142 nw.when = 'Both';
Daniel@0 143 if isamir(orig,'mirspectrum')
Daniel@0 144 nw.default = 0;
Daniel@0 145 elseif isamir(orig,'mirenvelope')
Daniel@0 146 nw.default = 'rectangular';
Daniel@0 147 else
Daniel@0 148 nw.default = 'hanning';
Daniel@0 149 end
Daniel@0 150 option.nw = nw;
Daniel@0 151
Daniel@0 152 win.key = 'Window';
Daniel@0 153 win.type = 'String';
Daniel@0 154 win.default = NaN;
Daniel@0 155 option.win = win;
Daniel@0 156
Daniel@0 157 specif.option = option;
Daniel@0 158
Daniel@0 159 specif.defaultframelength = 0.05;
Daniel@0 160 specif.defaultframehop = 0.5;
Daniel@0 161 specif.eachchunk = @eachchunk;
Daniel@0 162 specif.combinechunk = @combinechunk;
Daniel@0 163
Daniel@0 164 if isamir(orig,'mirscalar') || isamir(orig,'mirenvelope')
Daniel@0 165 specif.nochunk = 1;
Daniel@0 166 end
Daniel@0 167
Daniel@0 168 varargout = mirfunction(@mirautocor,orig,varargin,nargout,specif,@init,@main);
Daniel@0 169
Daniel@0 170
Daniel@0 171 function [x type] = init(x,option)
Daniel@0 172 type = 'mirautocor';
Daniel@0 173
Daniel@0 174
Daniel@0 175 function a = main(orig,option,postoption)
Daniel@0 176 if iscell(orig)
Daniel@0 177 orig = orig{1};
Daniel@0 178 end
Daniel@0 179 if isa(orig,'mirautocor')
Daniel@0 180 a = orig;
Daniel@0 181 if not(isempty(option)) && ...
Daniel@0 182 (option.min || iscell(option.max) || option.max < Inf)
Daniel@0 183 coeff = get(a,'Coeff');
Daniel@0 184 delay = get(a,'Delay');
Daniel@0 185 for h = 1:length(coeff)
Daniel@0 186 if a.freq
Daniel@0 187 mi = 1/option.max;
Daniel@0 188 ma = 1/option.min;
Daniel@0 189 else
Daniel@0 190 mi = option.min;
Daniel@0 191 ma = option.max;
Daniel@0 192 end
Daniel@0 193 for k = 1:length(coeff{h})
Daniel@0 194 range = find(and(delay{h}{k}(:,1,1) >= mi,...
Daniel@0 195 delay{h}{k}(:,1,1) <= ma));
Daniel@0 196 coeff{h}{k} = coeff{h}{k}(range,:,:);
Daniel@0 197 delay{h}{k} = delay{h}{k}(range,:,:);
Daniel@0 198 end
Daniel@0 199 end
Daniel@0 200 a = set(a,'Coeff',coeff,'Delay',delay);
Daniel@0 201 end
Daniel@0 202 if not(isempty(postoption)) && not(isequal(postoption,0))
Daniel@0 203 a = post(a,postoption);
Daniel@0 204 end
Daniel@0 205 elseif ischar(orig)
Daniel@0 206 a = mirautocor(miraudio(orig),option,postoption);
Daniel@0 207 else
Daniel@0 208 if nargin == 0
Daniel@0 209 orig = [];
Daniel@0 210 end
Daniel@0 211 a.freq = 0;
Daniel@0 212 a.ofspectrum = 0;
Daniel@0 213 a.window = {};
Daniel@0 214 a.normalwindow = 0;
Daniel@0 215 a = class(a,'mirautocor',mirdata(orig));
Daniel@0 216 a = purgedata(a);
Daniel@0 217 a = set(a,'Ord','coefficients');
Daniel@0 218 sig = get(orig,'Data');
Daniel@0 219 if isa(orig,'mirspectrum')
Daniel@0 220 a = set(a,'Title','Spectrum autocorrelation','OfSpectrum',1,...
Daniel@0 221 'Abs','frequency (Hz)');
Daniel@0 222 pos = get(orig,'Pos');
Daniel@0 223 else
Daniel@0 224 if isa(orig,'mirscalar')
Daniel@0 225 a = set(a,'Title',[get(orig,'Title') ' autocorrelation']);
Daniel@0 226 pos = get(orig,'FramePos');
Daniel@0 227 for k = 1:length(sig)
Daniel@0 228 for l = 1:length(sig{k})
Daniel@0 229 sig{k}{l} = sig{k}{l}';
Daniel@0 230 pos{k}{l} = pos{k}{l}(1,:,:)';
Daniel@0 231 end
Daniel@0 232 end
Daniel@0 233 else
Daniel@0 234 if isa(orig,'mirenvelope')
Daniel@0 235 a = set(a,'Title','Envelope autocorrelation');
Daniel@0 236 elseif not(isa(orig,'mirautocor'))
Daniel@0 237 a = set(a,'Title','Waveform autocorrelation');
Daniel@0 238 end
Daniel@0 239 pos = get(orig,'Pos');
Daniel@0 240 end
Daniel@0 241 a = set(a,'Abs','lag (s)');
Daniel@0 242 end
Daniel@0 243 f = get(orig,'Sampling');
Daniel@0 244
Daniel@0 245 if isnan(option.win)
Daniel@0 246 if isequal(option.nw,0) || ...
Daniel@0 247 strcmpi(option.nw,'Off') || strcmpi(option.nw,'No')
Daniel@0 248 option.win = 0;
Daniel@0 249 elseif isequal(option.nw,1) || strcmpi(option.nw,'On') || ...
Daniel@0 250 strcmpi(option.nw,'Yes')
Daniel@0 251 option.win = 'hanning';
Daniel@0 252 else
Daniel@0 253 option.win = postoption.nw;
Daniel@0 254 end
Daniel@0 255 end
Daniel@0 256
Daniel@0 257 coeff = cell(1,length(sig));
Daniel@0 258 lags = cell(1,length(sig));
Daniel@0 259 wind = cell(1,length(sig));
Daniel@0 260 for k = 1:length(sig)
Daniel@0 261 s = sig{k};
Daniel@0 262 p = pos{k};
Daniel@0 263 fk = f{k};
Daniel@0 264 if iscell(option.max)
Daniel@0 265 mi = option.min{k};
Daniel@0 266 ma = option.max{k};
Daniel@0 267 else
Daniel@0 268 mi = option.min;
Daniel@0 269 ma = option.max;
Daniel@0 270 end
Daniel@0 271 coeffk = cell(1,length(s));
Daniel@0 272 lagsk = cell(1,length(s));
Daniel@0 273 windk = cell(1,length(s));
Daniel@0 274 for l = 1:length(s)
Daniel@0 275 sl = s{l};
Daniel@0 276 sl(isnan(sl)) = 0;
Daniel@0 277 if option.ni
Daniel@0 278 mxsl = repmat(max(sl),[size(sl,1),1,1]);
Daniel@0 279 mnsl = repmat(min(sl),[size(sl,1),1,1]);
Daniel@0 280 sl = (sl-mnsl)./(mxsl-mnsl);
Daniel@0 281 end
Daniel@0 282 pl = p{l};
Daniel@0 283 pl = pl-repmat(pl(1,:,:),[size(pl,1),1,1]);
Daniel@0 284 ls = size(sl,1);
Daniel@0 285 if mi
Daniel@0 286 misp = find(pl(:,1,1)>=mi);
Daniel@0 287 if isempty(misp)
Daniel@0 288 warning('WARNING IN MIRAUTOCOR: The specified range of delays exceeds the temporal length of the signal.');
Daniel@0 289 disp('Minimum delay set to zero.')
Daniel@0 290 misp = 1; % misp is the lowest index of the lag range
Daniel@0 291 mi = 0;
Daniel@0 292 else
Daniel@0 293 misp = misp(1);
Daniel@0 294 end
Daniel@0 295 else
Daniel@0 296 misp = 1;
Daniel@0 297 end
Daniel@0 298 if ma
Daniel@0 299 masp = find(pl(:,1,1)>=ma);
Daniel@0 300 if isempty(masp)
Daniel@0 301 masp = Inf;
Daniel@0 302 else
Daniel@0 303 masp = masp(1);
Daniel@0 304 end
Daniel@0 305 else
Daniel@0 306 masp = Inf;
Daniel@0 307 end
Daniel@0 308 masp = min(masp,ceil(ls/2));
Daniel@0 309 if masp <= misp
Daniel@0 310 if size(sl,2) > 1
Daniel@0 311 warning('WARNING IN MIRAUTOCOR: Frame length is too small.');
Daniel@0 312 else
Daniel@0 313 warning('WARNING IN MIRAUTOCOR: The audio sequence is too small.');
Daniel@0 314 end
Daniel@0 315 display('The autocorrelation is not defined for this range of delays.');
Daniel@0 316 end
Daniel@0 317 sl = center(sl);
Daniel@0 318 if not(ischar(option.win)) || strcmpi(option.win,'Rectangular')
Daniel@0 319 kw = ones(size(sl));
Daniel@0 320 else
Daniel@0 321 N = size(sl,1);
Daniel@0 322 winf = str2func(option.win);
Daniel@0 323 try
Daniel@0 324 w = window(winf,N);
Daniel@0 325 catch
Daniel@0 326 if strcmpi(option.win,'hamming')
Daniel@0 327 disp('Signal Processing Toolbox does not seem to be installed. Recompute the hamming window manually.');
Daniel@0 328 w = 0.54 - 0.46 * cos(2*pi*(0:N-1)'/(N-1));
Daniel@0 329 else
Daniel@0 330 warning(['WARNING in MIRAUTOCOR: Unknown windowing function ',option.win,' (maybe Signal Processing Toolbox is not installed).']);
Daniel@0 331 disp('No windowing performed.')
Daniel@0 332 w = ones(size(sl,1),1);
Daniel@0 333 end
Daniel@0 334 end
Daniel@0 335 kw = repmat(w,[1,size(sl,2),size(sl,3)]);
Daniel@0 336 sl = sl.* kw;
Daniel@0 337 end
Daniel@0 338
Daniel@0 339 if strcmpi(option.scaleopt,'coeff')
Daniel@0 340 scaleopt = 'none';
Daniel@0 341 else
Daniel@0 342 scaleopt = option.scaleopt;
Daniel@0 343 end
Daniel@0 344 c = zeros(masp,size(sl,2),size(sl,3));
Daniel@0 345 for i = 1:size(sl,2)
Daniel@0 346 for j = 1:size(sl,3)
Daniel@0 347 if option.gener == 2
Daniel@0 348 cc = xcorr(sl(:,i,j),masp-1,scaleopt);
Daniel@0 349 c(:,i,j) = cc(masp:end);
Daniel@0 350 else
Daniel@0 351 ss = abs(fft(sl(:,i,j)));
Daniel@0 352 ss = ss.^option.gener;
Daniel@0 353 cc = ifft(ss);
Daniel@0 354 ll = (0:masp-1);
Daniel@0 355 c(:,i,j) = cc(ll+1);
Daniel@0 356 end
Daniel@0 357 end
Daniel@0 358 if strcmpi(option.scaleopt,'coeff') && option.gener == 2
Daniel@0 359 % to be adapted to generalized autocor
Daniel@0 360 c(:,i,:) = c(:,i,:)/xcorr(sum(sl(:,i,:),3),0);
Daniel@0 361 % This is a kind of generalization of the 'coeff'
Daniel@0 362 % normalization for multi-channels signals. In the
Daniel@0 363 % original 'coeff' option, the autocorrelation at zero
Daniel@0 364 % lag is identically 1.0. In this multi-channels
Daniel@0 365 % version, the autocorrelation at zero lag is such that
Daniel@0 366 % the sum over channels becomes identically 1.0.
Daniel@0 367 end
Daniel@0 368 end
Daniel@0 369 coeffk{l} = c(misp:end,:,:);
Daniel@0 370 pl = pl(find(pl(:,1,1) >=mi),:,:);
Daniel@0 371 lagsk{l} = pl(1:min(size(coeffk{l},1),size(pl,1)),:,:);
Daniel@0 372 windk{l} = kw;
Daniel@0 373 end
Daniel@0 374 coeff{k} = coeffk;
Daniel@0 375 lags{k} = lagsk;
Daniel@0 376 wind{k} = windk;
Daniel@0 377 end
Daniel@0 378 a = set(a,'Coeff',coeff,'Delay',lags,'Window',wind);
Daniel@0 379 if not(isempty(postoption))
Daniel@0 380 a = post(a,postoption);
Daniel@0 381 end
Daniel@0 382 end
Daniel@0 383
Daniel@0 384
Daniel@0 385 function a = post(a,option)
Daniel@0 386 debug = 0;
Daniel@0 387 coeff = get(a,'Coeff');
Daniel@0 388 lags = get(a,'Delay');
Daniel@0 389 wind = get(a,'Window');
Daniel@0 390 freq = option.fr && not(get(a,'FreqDomain'));
Daniel@0 391 if isequal(option.e,1)
Daniel@0 392 option.e = 2:10;
Daniel@0 393 end
Daniel@0 394 if max(option.e) > 1
Daniel@0 395 pa = mirpeaks(a,'NoBegin','NoEnd','Contrast',.01);
Daniel@0 396 va = mirpeaks(a,'Valleys','Contrast',.01);
Daniel@0 397 pv = get(pa,'PeakVal');
Daniel@0 398 vv = get(va,'PeakVal');
Daniel@0 399 end
Daniel@0 400 for k = 1:length(coeff)
Daniel@0 401 for l = 1:length(coeff{k})
Daniel@0 402 c = coeff{k}{l}; % Coefficients of autocorrelation
Daniel@0 403 t = lags{k}{l}; % Delays of autocorrelation
Daniel@0 404 if not(isempty(c))
Daniel@0 405 if not(isequal(option.nw,0) || strcmpi(option.nw,'No') || ...
Daniel@0 406 strcmpi(option.nw,'Off') || a.normalwindow) % 'NormalWindow' option
Daniel@0 407 xw = zeros(size(c));
Daniel@0 408 lc = size(c,1);
Daniel@0 409 for j = 1:size(c,3)
Daniel@0 410 for i = 1:size(c,2)
Daniel@0 411 xwij = xcorr(wind{k}{l}(:,i,j),lc,'coeff');
Daniel@0 412 xw(:,i,j) = xwij(lc+2:end);
Daniel@0 413 end
Daniel@0 414 end
Daniel@0 415 c = c./ xw;
Daniel@0 416 a.normalwindow = 1;
Daniel@0 417 end
Daniel@0 418 if ischar(option.reso) && ...
Daniel@0 419 (strcmpi(option.reso,'ToiviainenSnyder') || ...
Daniel@0 420 strcmpi(option.reso,'Toiviainen') || ...
Daniel@0 421 strcmpi(option.reso,'vanNoorden'))
Daniel@0 422 if isa(a,'mirautocor') && get(a,'FreqDomain')
Daniel@0 423 ll = 1./t;
Daniel@0 424 else
Daniel@0 425 ll = t;
Daniel@0 426 end
Daniel@0 427 if not(option.resocenter)
Daniel@0 428 option.resocenter = .5;
Daniel@0 429 end
Daniel@0 430 if strcmpi(option.reso,'ToiviainenSnyder') || ...
Daniel@0 431 strcmpi(option.reso,'Toiviainen')
Daniel@0 432 w = max(1 - 0.25*(log2(max(ll,1e-12)/option.resocenter)).^2, 0);
Daniel@0 433 elseif strcmpi(option.reso,'vanNoorden')
Daniel@0 434 f0=2.193; b=option.resocenter;
Daniel@0 435 f=1./ll; a1=(f0*f0-f.*f).^2+b*f.^2; a2=f0^4+f.^4;
Daniel@0 436 w=(1./sqrt(a1))-(1./sqrt(a2));
Daniel@0 437 end
Daniel@0 438 if max(w) == 0
Daniel@0 439 warning('The resonance curve, not defined for this range of delays, will not be applied.')
Daniel@0 440 else
Daniel@0 441 w = w/max(w);
Daniel@0 442 c = c.* repmat(w,[1,size(c,2),size(c,3)]);
Daniel@0 443 end
Daniel@0 444 end
Daniel@0 445 if option.h
Daniel@0 446 c = hwr(c);
Daniel@0 447 end
Daniel@0 448 if max(option.e) > 1
Daniel@0 449 if a.freq
Daniel@0 450 freq = 1;
Daniel@0 451 for i = 1:size(c,3)
Daniel@0 452 c(:,:,i) = flipud(c(:,:,i));
Daniel@0 453 end
Daniel@0 454 t = flipud(1./t);
Daniel@0 455 end
Daniel@0 456
Daniel@0 457 for g = 1:size(c,2)
Daniel@0 458 for h = 1:size(c,3)
Daniel@0 459 cgh = c(:,g,h);
Daniel@0 460 if length(cgh)>1
Daniel@0 461 pvk = pv{k}{l}{1,g,h};
Daniel@0 462 mv = [];
Daniel@0 463 if not(isempty(pvk))
Daniel@0 464 mp = min(pv{k}{l}{1,g,h}); %Lowest peak
Daniel@0 465 vvv = vv{k}{l}{1,g,h}; %Valleys
Daniel@0 466 mv = vvv(find(vvv<mp,1,'last'));
Daniel@0 467 %Highest valley below the lowest peak
Daniel@0 468
Daniel@0 469 if not(isempty(mv))
Daniel@0 470 cgh = cgh-mv;
Daniel@0 471 end
Daniel@0 472 end
Daniel@0 473 cgh2 = cgh;
Daniel@0 474 tgh2 = t(:,g,1);
Daniel@0 475 coef = cgh(2)-cgh(1); % initial slope of the autocor curve
Daniel@0 476 tcoef = tgh2(2)-tgh2(1);
Daniel@0 477 deter = 0;
Daniel@0 478 inter = 0;
Daniel@0 479
Daniel@0 480 repet = find(not(diff(tgh2))); % Avoid bug if repeated x-values
Daniel@0 481 if repet
Daniel@0 482 warning('WARNING in MIRAUTOCOR: Two successive samples have exactly same temporal position.');
Daniel@0 483 tgh2(repet+1) = tgh2(repet)+1e-12;
Daniel@0 484 end
Daniel@0 485
Daniel@0 486 if coef < 0
Daniel@0 487 % initial descending slope removed
Daniel@0 488 deter = find(diff(cgh2)>0,1)-1;
Daniel@0 489 % number of removed points
Daniel@0 490 if isempty(deter)
Daniel@0 491 deter = 0;
Daniel@0 492 end
Daniel@0 493 cgh2(1:deter) = [];
Daniel@0 494 tgh2(1:deter) = [];
Daniel@0 495 coef = cgh2(2)-cgh2(1);
Daniel@0 496 end
Daniel@0 497
Daniel@0 498 if coef > 0
Daniel@0 499 % initial ascending slope prolonged to the left
Daniel@0 500 % until it reaches the x-axis
Daniel@0 501 while cgh2(1) > 0
Daniel@0 502 coef = coef*1.1;
Daniel@0 503 % the further to the left, ...
Daniel@0 504 % the more ascending is the slope
Daniel@0 505 % (not sure it always works, though...)
Daniel@0 506 inter = inter+1;
Daniel@0 507 % number of added points
Daniel@0 508 cgh2 = [cgh2(1)-coef; cgh2];
Daniel@0 509 tgh2 = [tgh2(1)-tcoef; tgh2];
Daniel@0 510 end
Daniel@0 511 cgh2(1) = 0;
Daniel@0 512 end
Daniel@0 513
Daniel@0 514 for i = option.e % Enhancing procedure
Daniel@0 515 % option.e is the list of scaling factors
Daniel@0 516 % i is the scaling factor
Daniel@0 517 if i
Daniel@0 518 be = find(tgh2 & tgh2/i >= tgh2(1),1);
Daniel@0 519 % starting point of the substraction
Daniel@0 520 % on the X-axis
Daniel@0 521
Daniel@0 522 if not(isempty(be))
Daniel@0 523 ic = interp1(tgh2,cgh2,tgh2/i);
Daniel@0 524 % The scaled autocorrelation
Daniel@0 525 ic(1:be-1) = 0;
Daniel@0 526 ic(find(isnan(ic))) = Inf;
Daniel@0 527 % All the NaN values are changed
Daniel@0 528 % into 0 in the resulting curve
Daniel@0 529 ic = max(ic,0);
Daniel@0 530
Daniel@0 531 if debug
Daniel@0 532 hold off,plot(tgh2,cgh2)
Daniel@0 533 end
Daniel@0 534
Daniel@0 535 cgh2 = cgh2 - ic;
Daniel@0 536 % The scaled autocorrelation
Daniel@0 537 % is substracted to the initial one
Daniel@0 538
Daniel@0 539 cgh2 = max(cgh2,0);
Daniel@0 540 % Half-wave rectification
Daniel@0 541
Daniel@0 542 if debug
Daniel@0 543 hold on,plot(tgh2,ic,'r')
Daniel@0 544 hold on,plot(tgh2,cgh2,'g')
Daniel@0 545 drawnow
Daniel@0 546 figure
Daniel@0 547 end
Daniel@0 548 end
Daniel@0 549 end
Daniel@0 550 end
Daniel@0 551
Daniel@0 552 % The temporary modifications are
Daniel@0 553 % removed from the final curve
Daniel@0 554 if inter>=deter
Daniel@0 555 c(:,g,h) = cgh2(inter-deter+1:end);
Daniel@0 556 if not(isempty(mv))
Daniel@0 557 c(:,g,h) = c(:,g,h) + mv;
Daniel@0 558 end
Daniel@0 559 else
Daniel@0 560 c(:,g,h) = [zeros(deter-inter,1);cgh2];
Daniel@0 561 end
Daniel@0 562 end
Daniel@0 563 end
Daniel@0 564 end
Daniel@0 565 end
Daniel@0 566 if freq
Daniel@0 567 if t(1,1) == 0
Daniel@0 568 c = c(2:end,:,:);
Daniel@0 569 t = t(2:end,:,:);
Daniel@0 570 end
Daniel@0 571 for i = 1:size(c,3)
Daniel@0 572 c(:,:,i) = flipud(c(:,:,i));
Daniel@0 573 end
Daniel@0 574 t = flipud(1./t);
Daniel@0 575 end
Daniel@0 576 coeff{k}{l} = c;
Daniel@0 577 lags{k}{l} = t;
Daniel@0 578 end
Daniel@0 579 end
Daniel@0 580 end
Daniel@0 581 a = set(a,'Coeff',coeff,'Delay',lags,'Freq');
Daniel@0 582 if freq
Daniel@0 583 a = set(a,'FreqDomain',1,'Abs','frequency (Hz)');
Daniel@0 584 end
Daniel@0 585
Daniel@0 586
Daniel@0 587 function [y orig] = eachchunk(orig,option,missing,postchunk)
Daniel@0 588 option.scaleopt = 'none';
Daniel@0 589 y = mirautocor(orig,option);
Daniel@0 590
Daniel@0 591
Daniel@0 592 function y = combinechunk(old,new)
Daniel@0 593 do = get(old,'Data');
Daniel@0 594 do = do{1}{1};
Daniel@0 595 dn = get(new,'Data');
Daniel@0 596 dn = dn{1}{1};
Daniel@0 597 if abs(size(dn,1)-size(do,1)) <= 2 % Probleme of border fluctuation
Daniel@0 598 mi = min(size(dn,1),size(do,1));
Daniel@0 599 dn = dn(1:mi,:,:);
Daniel@0 600 do = do(1:mi,:,:);
Daniel@0 601 elseif length(dn) < length(do)
Daniel@0 602 dn(length(do),:,:) = 0; % Zero-padding
Daniel@0 603 end
Daniel@0 604 y = set(old,'ChunkData',do+dn);