Mercurial > hg > ltpda
diff m-toolbox/classes/@ao/computeDFT.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@ao/computeDFT.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,124 @@ +% COMPUTEDFT Computes DFT using FFT or Goertzel +% This function is used to calculate the DFT of a signal using the FFT +% or the Goertzel algorithm. +% +% [XX,F] = COMPUTEDFT(XIN,NFFT) where NFFT is a scalar and computes the +% DFT XX using FFT. F is the frequency points at which the XX is +% computed and is of length NFFT. +% +% [XX,F] = COMPUTEDFT(XIN,F) where F is a vector with atleast two +% elements computes the DFT XX using the Goertzel algorithm. +% +% [XX,F] = COMPUTEDFT(...,Fs) returns the frequency vector F (in hz) +% where Fs is the sampling frequency +% +% Inputs: +% XIN is the input signal +% NFFT if a scalar corresponds to the number of FFT points used to +% calculate the DFT using FFT. +% NFFT if a vector corresponds to the frequency points at which the DFT +% is calculated using goertzel. +% FS is the sampling frequency +% +% A direct copy of MATLAB's function for LTPDA +% +% M Hewitson 08-05-08 +% +% $Id: computeDFT.m,v 1.2 2008/08/01 13:19:42 ingo Exp $ +% + +% Copyright 2006 The MathWorks, Inc. + +% [1] Oppenheim, A.V., and R.W. Schafer, Discrete-Time Signal Processing, +% Prentice-Hall, Englewood Cliffs, NJ, 1989, pp. 713-718. +% [2] Mitra, S. K., Digital Signal Processing. A Computer-Based Approach. +% 2nd Ed. McGraw-Hill, N.Y., 2001. + +function [Xx,f] = computeDFT(xin,nfft,varargin) + + error(nargchk(2,3,nargin,'struct')); + if nargin > 2, + Fs = varargin{1}; + else + Fs = 2*pi; + end + + nx = size(xin,1); + + if length(nfft) > 1, + isfreqVector = true; + else + isfreqVector = false; + end + + if ~isfreqVector, + [Xx,f] = computeDFTviaFFT(xin,nx,nfft,Fs); + else + [Xx,f] = computeDFTviaGoertzel(xin,nfft,Fs); + end + +end + +%------------------------------------------------------------------------- +function [Xx,f] = computeDFTviaFFT(xin,nx,nfft,Fs) + % Use FFT to compute raw STFT and return the F vector. + + % Handle the case where NFFT is less than the segment length, i.e., "wrap" + % the data as appropriate. + xin_ncol = size(xin,2); + xw = zeros(nfft,xin_ncol); + if nx > nfft, + for j = 1:xin_ncol, + xw(:,j) = datawrap(xin(:,j),nfft); + end + else + xw = xin; + end + + Xx = fft(xw,nfft); + f = psdfreqvec('npts',nfft,'Fs',Fs); +end + +%-------------------------------------------------------------------------- +function [Xx,f] = computeDFTviaGoertzel(xin,freqvec,Fs) + % Use Goertzel to compute raw DFT and return the F vector. + + f = freqvec(:); + f = mod(f,Fs); % 0 <= f < = Fs + nfld = floor(freqvec(:)/Fs); + xm = size(xin,1); % NFFT + + % Indices used by the Goertzel function (see equation 11.1 pg. 755 of [2]) + fscaled = f/Fs*xm+1; + k = round(fscaled); + + % shift for each frequency from default xm length grid + deltak = fscaled-k; + + tempk = k; + % If k > xm, fold over to the 1st bin + k(tempk > xm) = 1; + nfld = nfld + (tempk > xm); % Make nfld reflect fold in k because of round + + n = (0:xm-1)'; + Xx = zeros(size(k,1),size(xin,2)); + for kindex = 1:length(k) + % We need to evaluate the DFT at the requested frequency instead of a + % neighboring frequency that lies on the grid obtained with xm number + % of points in the 0 to fs range. We do that by giving a complex phase + % to xin equal to the offset from the frequency to its nearest neighbor + % on the grid. This phase translates into a shift in the DFT by the + % same amount. The Xx(k) then is the DFT at (k+deltak). + + % apply kernal to xin so as to evaluate DFT at k+deltak) + kernel = exp(-j*2*pi*deltak(kindex)/xm*n); + xin_phaseshifted = xin.*repmat(kernel,1,size(xin,2)); + + Xx(kindex,:) = goertzel(xin_phaseshifted,k(kindex)); + end + + % DFT computed at exactly the frequencies it was requested for + f = freqvec(:); +end + +