yading@10
|
1
|
yading@10
|
2 function [f0, f0error] = TWM (ploc, pmag, N, fs, minf0, maxf0)
|
yading@10
|
3 % Two-way mismatch algorithm (by Beauchamp&Maher)
|
yading@10
|
4 % ploc, pmag: peak locations and magnitudes, N: size of complex spectrum
|
yading@10
|
5 % fs: sampling rate of sound, minf0: minimum f0, maxf0: maximum f0
|
yading@10
|
6 % f0: fundamental frequency detected, f0error: error measure
|
yading@10
|
7 pfreq = (ploc-1)/N*fs; % frequency in Hertz of peaks
|
yading@10
|
8 [zvalue,zindex] = min(pfreq);
|
yading@10
|
9 if (zvalue==0) % avoid zero frequency peak
|
yading@10
|
10 pfreq(zindex) = 1;
|
yading@10
|
11 pmag(zindex) = -100;
|
yading@10
|
12 end
|
yading@10
|
13 ival2 = pmag;
|
yading@10
|
14 [Mmag1,Mloc1] = max(ival2); % find peak with maximum magnitude
|
yading@10
|
15 ival2(Mloc1) = -100; % clear max peak
|
yading@10
|
16 [Mmag2,Mloc2]= max(ival2); % find second maximum magnitude peak
|
yading@10
|
17 ival2(Mloc2) = -100; % clear second max peak
|
yading@10
|
18 [Mmag3,Mloc3]= max(ival2); % find third maximum magnitude peak
|
yading@10
|
19 nCand = 3; % number of possible f0 candidates for each max peak
|
yading@10
|
20 f0c = zeros(1,3*nCand); % initialize array of candidates
|
yading@10
|
21 f0c(1:nCand)=(pfreq(Mloc1)*ones(1,nCand))./((nCand+1-(1:nCand))); % candidates
|
yading@10
|
22 f0c(nCand+1:nCand*2)=(pfreq(Mloc2)*ones(1,nCand))./((nCand+1-(1:nCand)));
|
yading@10
|
23 f0c(nCand*2+1:nCand*3)=(pfreq(Mloc3)*ones(1,nCand))./((nCand+1-(1:nCand)));
|
yading@10
|
24 f0c = f0c((f0c<maxf0)&(f0c>minf0)); % candidates within boundaries
|
yading@10
|
25 if (isempty(f0c)) % if no candidates exit
|
yading@10
|
26 f0 = 0; f0error=100;
|
yading@10
|
27 return
|
yading@10
|
28 end
|
yading@10
|
29 harmonic = f0c;
|
yading@10
|
30 ErrorPM = zeros(fliplr(size(harmonic))); % initialize PM errors
|
yading@10
|
31 MaxNPM = min(10,length(ploc));
|
yading@10
|
32 for i=1:MaxNPM % predicted to measured mismatch error
|
yading@10
|
33 difmatrixPM = harmonic' * ones(size(pfreq))';
|
yading@10
|
34 difmatrixPM = abs(difmatrixPM-ones(fliplr(size(harmonic)))*pfreq');
|
yading@10
|
35 [FreqDistance,peakloc] = min(difmatrixPM,[],2);
|
yading@10
|
36 Ponddif = FreqDistance .* (harmonic'.^(-0.5));
|
yading@10
|
37 PeakMag = pmag(peakloc);
|
yading@10
|
38 MagFactor = 10.^((PeakMag-Mmag1)./20);
|
yading@10
|
39 ErrorPM = ErrorPM+(Ponddif+MagFactor.*(1.4*Ponddif-0.5));
|
yading@10
|
40 harmonic = harmonic+f0c;
|
yading@10
|
41 end
|
yading@10
|
42 ErrorMP = zeros(fliplr(size(harmonic))); % initialize MP errors
|
yading@10
|
43 MaxNMP = min(10,length(pfreq));
|
yading@10
|
44 for i=1:length(f0c) % measured to predicted mismatch error
|
yading@10
|
45 nharm = round(pfreq(1:MaxNMP)/f0c(i));
|
yading@10
|
46 nharm = (nharm>=1).*nharm + (nharm<1);
|
yading@10
|
47 FreqDistance = abs(pfreq(1:MaxNMP) - nharm*f0c(i));
|
yading@10
|
48 Ponddif = FreqDistance.* (pfreq(1:MaxNMP).^(-0.5));
|
yading@10
|
49 PeakMag = pmag(1:MaxNMP);
|
yading@10
|
50 MagFactor = 10.^((PeakMag-Mmag1)./20);
|
yading@10
|
51 ErrorMP(i) = sum(MagFactor.*(Ponddif+MagFactor.*(1.4*Ponddif-0.5)));
|
yading@10
|
52 end
|
yading@10
|
53 Error = (ErrorPM/MaxNPM) + (0.3*ErrorMP/MaxNMP); % total errors
|
yading@10
|
54 [f0error, f0index] = min(Error); % get the smallest error
|
yading@10
|
55 f0 = f0c(f0index); % f0 with the smallest error |