www.pudn.com > LPCToolbox.rar > GETPEAKS.M


%--------------------------------- 
%  [estpk,rawpk] = getpeaks(a, fftlen, Fs) 
%    a is the list of linear prediction coefficients. GETPEAKS 
%    estimates the locations of the peaks and their bandwidths in the 
%    spectrum of 'a', using a peak-picking + parabolic interpolation 
%    method. See Markel & Gray, 1976, Sec. 7.2.2 for details. 
%     
%    a : lpc coeffs 
%    fftlen: zero-padded length for fft 
%    Fs: sampling frequency 
% 
%   rawpk, estpk   : Nx2 matrices, N=# of peaks 
%           pk(:,1) = locations of peaks (w.r.t. Fs) 
%           pk(:,2) = corr. bandwidths  
% 
%--------------------------------- 
function [estpk,rawpk] = getpeaks(a, fftlen, Fs) 
 
F = fft(a,fftlen);          % zero-padded to fftlen 
 
fx = powerspectrum(F);      % all-zero power spectrum, with only 
                            % positive frequencies. 
 
ts = Fs/fftlen;             % frequency resolution 
 
% find the extrema, and do the 3pt parabolic interpolation 
% to find the "true" location of each valley. 
 
l=minima(fx); 
   
rawpk = []; estpk = []; 
for i=1:length(l), 
  j = l(i);        % j = location of the i'th peak 
  [fn,fi,bw] = threepointinterp(fx, j, ts);  
  rawpk(i,:) = floor([fn  0]); 
  estpk(i,:) = floor([fi bw]); 
end 
   
rawpk = [rawpk; 0 0; 0 0; 0 0]; % in case there are too few formants 
estpk = [estpk; 0 0; 0 0; 0 0]; 
   
%================================================================ 
 
%--------------------------------- 
% [fn, fi] = threepointinterp(f, j, ts) 
% 
%   Estimate the "true peak" using three-point parabolic  
%   interpolation. See Markel & Gray, 1976, Sec 7.2.2.,  
%   eqns. 7.4 & 7.5. 
% 
%   f = spectrum, j = location of the i'th peak 
%   ts = frequency quantum 
% 
%   fn : quantal (or raw) peak 
%   fi : estimated peak 
%   bw : est. bandwidth of estimated peak 
% 
%--------------------------------- 
 
function [fn, fi, bw] = threepointinterp(f, j, ts) 
 
 % We (along with ILS) use (j-1)*ts since the array indices 
 % start with 1. So j=1 => 0 Hz, j=2 => 1*ts Hz, etc. 
 
 fn = (j-1) * ts; 
 
 fj = 1 / f(j);       % these inversions are for the 
 fjm1 = 1 / f(j-1);   % all-zero -> all-pole adjustment 
 fjp1 = 1 / f(j+1);   % (so that we get the right values 
                      % for the amplitudes [pk]). 
 
 %------------ 
 % The Markel & Gray algorithm is implemented in a 
 % somewhat convoluted way in ILS. This has been 
 % duplicated for authenticity. For comparision, 
 % here is a more understandable implementation: 
 % 
 % aa = (fjm1+fjp1)/2 - fj; 
 % bb = (fjp1-fjm1)/2; 
 % cc = fj; 
 % delta = (-bb/(2*aa)) * ts; 
 % fi = delta + fn; % fi=location of the peak 
 %------------ 
 
 % The following code is the convoluted implementation,  
 % which is pretty much copied directly from ILS. 
 
 tss = ts*ts; 
 
 %------ location of peak  
 
 aa = (fjm1 - 2*fj) + fjp1; 
 aa = aa * (0.5/tss); 
 
 bb = (fjp1-fjm1) * (0.5/ts); 
 fi = - bb*(0.5/aa) + fn;       % fi=location of the peak 
 
 %------ bandwidth 
 
 cc = fj; 
 ee = cc - (bb*bb)*(.25/aa); 
 dd = cc - 0.5*ee; 
 gg = (bb*bb) - 4*(aa*dd);  
 
 bw = - sqrt(gg) / aa;      % bw=bandwidth 
 pk = ee;                   % estimated amplitude of the peak  
 
%=============================================================== 
% ps = powerspectrum(F) 
%  F is the a complex spectrum (the output of FFT). Throw out  
%  the negative frequencies, and convert to a power spectrum (ps). 
 
function  ps = powerspectrum(F) 
 
n = length(F);    
i = [1:ceil(n/2)]; 
 
ps = abs(F(i)) .^ 2; 
 
%    f  : digital frequencies for ps. Multiply by Fs to 
%         get the analog frequencies. 
% 
% f = (i-1) * (1/n); 
 
%=============================================================== 
% l = minima(x) 
% 
% find when der(x) goes from neg to pos. 
% output l (list of indices) is sorted. 
 
function l = minima(x) 
 
% x(3:end)    a b|c d e f g ... x y z| 
% x(2:end-1)    a|b c d e f g ... x y|z 
% x(1:end-2)     |a b c d e f g ... x|y z 
 
d1 = x(2:end-1) - x(1:end-2); 
d2 = x(3:end)   - x(2:end-1); 
i = find((d1 < 0) & (d2 > 0)); 
 
% d1 and d2 are indexed w.r.t. x(2:end-1). Update 
% the locations of the minima so that they are indexed 
% w.r.t. x(1:end). 
 
l = i+1;