www.gusucode.com > signal 工具箱matlab源码程序 > signal/spectrum.m
function [Spec,f] = spectrum(varargin) %SPECTRUM Spectral Estimation. % % SPECTRUM will be removed in a future release of MATLAB. Use one of the % following functions instead: % <a href="matlab:help periodogram">periodogram</a> % <a href="matlab:help pwelch">pwelch</a> % <a href="matlab:help pburg">pburg</a> % <a href="matlab:help pcov">pcov</a> % <a href="matlab:help pmcov">pmcov</a> % <a href="matlab:help pyulear">pyulear</a> % <a href="matlab:help pmtm">pmtm</a> % <a href="matlab:help peig">peig</a> % <a href="matlab:help pmusic">pmusic</a> % <a href="matlab:help tfestimate">tfestimate</a> % <a href="matlab:help mscohere">mscohere</a> % % <a href="matlab:help signal">Signal Processing Toolbox TOC</a> % H = SPECTRUM.<ESTIMATOR> returns a spectral estimator in H of type % specified by ESTIMATOR. % % There are three types of estimators: power spectral density (PSD), % mean-square spectrum (MSS), and pseudo spectrum. Valid values for % <ESTIMATOR> for each of these three types are listed below. Type % "help spectrum.<ESTIMATOR>" to get help on a specific spectrum % estimator e.g., "help spectrum.welch": % % ---------------------------- % Power spectral density (PSD) % ---------------------------- % <a href="matlab:help spectrum.burg">burg</a> - Burg <a href="matlab:help spectrum.periodogram">periodogram</a> - Periodogram % <a href="matlab:help spectrum.cov">cov</a> - Covariance <a href="matlab:help spectrum.welch">welch</a> - Welch % <a href="matlab:help spectrum.mcov">mcov</a> - Modified Covariance <a href="matlab:help spectrum.yulear">yulear</a> - Yule-Walker AR % <a href="matlab:help spectrum.mtm">mtm</a> - Thomson multitaper method (MTM) % % To calculate the PSD you must create one of the estimators above and % pass it to one of the functions below along with the data. % % <a href="matlab:help spectrum/psd">psd</a> - calculates the PSD % <a href="matlab:help spectrum/psdopts">psdopts</a> - options to calculate the PSD % % -------------------------- % Mean-square spectrum (MSS) % -------------------------- % <a href="matlab:help spectrum.periodogram">periodogram</a> - Periodogram % <a href="matlab:help spectrum.welch">welch</a> - Welch % % To calculate the MSS you must create one of the estimators above and % pass it to one of the functions below along with the data. % % <a href="matlab:help spectrum/msspectrum">msspectrum</a> - calculates the Mean-squared Spectrum (MSS) % <a href="matlab:help spectrum/msspectrumopts">msspectrumopts</a> - options to calculate the MSS % % --------------- % Pseudo spectrum % --------------- % <a href="matlab:help spectrum.eigenvector">eigenvector</a> - Eigenvector % <a href="matlab:help spectrum.music">music</a> - Multiple Signal Classification % % To calculate the pseudo spectrum you must create one of the estimators % above and pass it to one of the functions below along with the data. % % <a href="matlab:help spectrum/powerest">powerest</a> - computes the powers and frequencies of sinusoids % <a href="matlab:help spectrum/pseudospectrum">pseudospectrum</a> - calculates the pseudospectrum % <a href="matlab:help spectrum/pseudospectrumopts.">pseudospectrumopts</a> - options to calculate the pseudospectrum % % EXAMPLE: Spectral analysis of a signal that contains a 200Hz cosine % % plus noise. % Fs = 1000; t = 0:1/Fs:.296; % x = cos(2*pi*t*200)+randn(size(t)); % h = spectrum.welch; % Create a Welch spectral estimator. % % Hpsd = psd(h,x,'Fs',Fs); % Calculate the PSD % plot(Hpsd) % Plot the PSD. % % % See also DSPDATA. % Author(s): J.N. Little, 7-9-86 % C. Denham, 4-25-88, revised % L. Shure, 12-20-88, revised % J.N. Little, 8-31-89, revised % L. Shure, 8-11-92, revised % T. Krauss, 4-15-93, revised % Copyright 1988-2012 The MathWorks, Inc. % The units on the power spectra Pxx and Pyy are such that, using % Parseval's theorem: % % SUM(Pxx)/LENGTH(Pxx) = SUM(X.^2)/LENGTH(X) = COV(X) % % The RMS value of the signal is the square root of this. % If the input signal is in Volts as a function of time, then % the units on Pxx are Volts^2*seconds = Volt^2/Hz. % % Here are the covariance, RMS, and spectral amplitude values of % some common functions: % Function Cov=SUM(Pxx)/LENGTH(Pxx) RMS Pxx % a*sin(w*t) a^2/2 a/sqrt(2) a^2*LENGTH(Pxx)/4 %Normal: a*rand(t) a^2 a a^2 %Uniform: a*rand(t) a^2/12 a/sqrt(12) a^2/12 % % For example, a pure sine wave with amplitude A has an RMS value % of A/sqrt(2), so A = SQRT(2*SUM(Pxx)/LENGTH(Pxx)). % % See Page 556, A.V. Oppenheim and R.W. Schafer, Digital Signal % Processing, Prentice-Hall, 1975. % Obsolete in 2007a. warning(message('signal:spectrum:obsoleteFunction')); narginchk(1,8) [x,y,nfft,noverlap,window,Fs,p,dflag]=specchk(varargin); if isempty(p), p = .95; % default confidence interval even if not asked for end n = length(x); % Number of data points nwind = length(window); if n < nwind % zero-pad x (and y) if length less than the window length x(nwind)=0; n=nwind; if ~isempty(y), y(nwind)=0; end end x = x(:); % Make sure x and y are column vectors y = y(:); k = fix((n-noverlap)/(nwind-noverlap)); % Number of windows % (k = fix(n/nwind) for noverlap=0) index = 1:nwind; KMU = k*norm(window)^2; % Normalizing scale factor ==> asymptotically unbiased % KMU = k*sum(window)^2;% alt. Nrmlzng scale factor ==> peaks are about right if (isempty(y)) % Single sequence case. Pxx = zeros(nfft,1); Pxx2 = zeros(nfft,1); for i=1:k if strcmp(dflag,'linear') xw = window.*detrend(x(index)); elseif strcmp(dflag,'none') xw = window.*(x(index)); else xw = window.*detrend(x(index),0); end index = index + (nwind - noverlap); Xx = abs(fft(xw,nfft)).^2; Pxx = Pxx + Xx; Pxx2 = Pxx2 + abs(Xx).^2; end % Select first half if ~any(any(imag(x)~=0)), % if x and y are not complex if rem(nfft,2), % nfft odd select = 1:(nfft+1)/2; else select = 1:nfft/2+1; % include DC AND Nyquist end else select = 1:nfft; end Pxx = Pxx(select); Pxx2 = Pxx2(select); cPxx = zeros(size(Pxx)); if k > 1 c = (k.*Pxx2-abs(Pxx).^2)./(k-1); c = max(c,zeros(size(Pxx))); cPxx = sqrt(c); end ff = sqrt(2)*erfinv(p); % Equal-tails. Pxx = Pxx/KMU; Pxxc = ff.*cPxx/KMU; P = [Pxx Pxxc]; else Pxx = zeros(nfft,1); % Dual sequence case. Pyy = Pxx; Pxy = Pxx; Pxx2 = Pxx; Pyy2 = Pxx; Pxy2 = Pxx; for i=1:k if strcmp(dflag,'linear') xw = window.*detrend(x(index)); yw = window.*detrend(y(index)); elseif strcmp(dflag,'none') xw = window.*(x(index)); yw = window.*(y(index)); else xw = window.*detrend(x(index),0); yw = window.*detrend(y(index),0); end index = index + (nwind - noverlap); Xx = fft(xw,nfft); Yy = fft(yw,nfft); Yy2 = abs(Yy).^2; Xx2 = abs(Xx).^2; Xy = Yy .* conj(Xx); Pxx = Pxx + Xx2; Pyy = Pyy + Yy2; Pxy = Pxy + Xy; Pxx2 = Pxx2 + abs(Xx2).^2; Pyy2 = Pyy2 + abs(Yy2).^2; Pxy2 = Pxy2 + Xy .* conj(Xy); end % Select first half if ~any(any(imag([x y])~=0)), % if x and y are not complex if rem(nfft,2), % nfft odd select = 1:(nfft+1)/2; else select = 1:nfft/2+1; % include DC AND Nyquist end else select = 1:nfft; end Pxx = Pxx(select); Pyy = Pyy(select); Pxy = Pxy(select); Pxx2 = Pxx2(select); Pyy2 = Pyy2(select); Pxy2 = Pxy2(select); cPxx = zeros(size(Pxx)); cPyy = cPxx; cPxy = cPxx; if k > 1 c = max((k.*Pxx2-abs(Pxx).^2)./(k-1),zeros(size(Pxx))); cPxx = sqrt(c); c = max((k.*Pyy2-abs(Pyy).^2)./(k-1),zeros(size(Pxx))); cPyy = sqrt(c); c = max((k.*Pxy2-abs(Pxy).^2)./(k-1),zeros(size(Pxx))); cPxy = sqrt(c); end Txy = Pxy./Pxx; Cxy = (abs(Pxy).^2)./(Pxx.*Pyy); ff = sqrt(2)*erfinv(p); % Equal-tails. Pxx = Pxx/KMU; Pyy = Pyy/KMU; Pxy = Pxy/KMU; Pxxc = ff.*cPxx/KMU; Pxyc = ff.*cPxy/KMU; Pyyc = ff.*cPyy/KMU; P = [Pxx Pyy Pxy Txy Cxy Pxxc Pyyc Pxyc]; end freq_vector = (select - 1)'*Fs/nfft; if nargout == 0, % do plots newplot; c = [max(Pxx-Pxxc,0) Pxx+Pxxc]; c = c.*(c>0); semilogy(freq_vector,Pxx,freq_vector,c(:,1),'--',... freq_vector,c(:,2),'--'); title('Pxx - X Power Spectral Density') xlabel('Frequency') if (isempty(y)), % single sequence case return end pause newplot; c = [max(Pyy-Pyyc,0) Pyy+Pyyc]; c = c.*(c>0); semilogy(freq_vector,Pyy,freq_vector,c(:,1),'--',... freq_vector,c(:,2),'--'); title('Pyy - Y Power Spectral Density') xlabel('Frequency') pause newplot; semilogy(freq_vector,abs(Txy)); title('Txy - Transfer function magnitude') xlabel('Frequency') pause newplot; plot(freq_vector,180/pi*angle(Txy)), ... title('Txy - Transfer function phase') xlabel('Frequency') pause newplot; plot(freq_vector,Cxy); title('Cxy - Coherence') xlabel('Frequency') elseif nargout ==1, Spec = P; elseif nargout ==2, Spec = P; f = freq_vector; end function [x,y,nfft,noverlap,window,Fs,p,dflag] = specchk(P) %SPECCHK Helper function for SPECTRUM % SPECCHK(P) takes the cell array P and uses each cell as % an input argument. Assumes P has between 1 and 7 elements. % Author(s): T. Krauss, 4-6-93 if length(P{1})<=1 error(message('signal:spectrum:InvalidInput')); elseif (length(P)>1), if (all(size(P{1})==size(P{2})) && (length(P{1})>1) ) || ... length(P{2})>1, % 0ne signal or 2 present? % two signals, x and y, present x = P{1}; y = P{2}; % shift parameters one left P(1) = []; else % only one signal, x, present x = P{1}; y = []; end else % length(P) == 1 % only one signal, x, present x = P{1}; y = []; end % now x and y are defined; let's get the rest if length(P) == 1 nfft = min(length(x),256); window = hanning(nfft); noverlap = 0; Fs = 2; p = []; dflag = 'linear'; elseif length(P) == 2 if isempty(P{2}), dflag = 'linear'; nfft = min(length(x),256); elseif ischar(P{2}), dflag = P{2}; nfft = min(length(x),256); else dflag = 'linear'; nfft = P{2}; end window = hanning(nfft); noverlap = 0; Fs = 2; p = []; elseif length(P) == 3 if isempty(P{2}), nfft = min(length(x),256); else nfft=P{2}; end if isempty(P{3}), dflag = 'linear'; noverlap = 0; elseif ischar(P{3}), dflag = P{3}; noverlap = 0; else dflag = 'linear'; noverlap = P{3}; end window = hanning(nfft); Fs = 2; p = []; elseif length(P) == 4 if isempty(P{2}), nfft = min(length(x),256); else nfft=P{2}; end if ischar(P{4}) dflag = P{4}; window = hanning(nfft); else dflag = 'linear'; window = P{4}; window = window(:); % force window to be a column if length(window) == 1, window = hanning(window); end if isempty(window), window = hanning(nfft); end end if isempty(P{3}), noverlap = 0; else noverlap=P{3}; end Fs = 2; p = []; elseif length(P) == 5 if isempty(P{2}), nfft = min(length(x),256); else nfft=P{2}; end window = P{4}; window = window(:); % force window to be a column if length(window) == 1, window = hanning(window); end if isempty(window), window = hanning(nfft); end if isempty(P{3}), noverlap = 0; else noverlap=P{3}; end if ischar(P{5}) dflag = P{5}; Fs = 2; else dflag = 'linear'; if isempty(P{5}), Fs = 2; else Fs = P{5}; end end p = []; elseif length(P) == 6 if isempty(P{2}), nfft = min(length(x),256); else nfft=P{2}; end window = P{4}; window = window(:); % force window to be a column if length(window) == 1, window = hanning(window); end if isempty(window), window = hanning(nfft); end if isempty(P{3}), noverlap = 0; else noverlap=P{3}; end if isempty(P{5}), Fs = 2; else Fs = P{5}; end if ischar(P{6}) dflag = P{6}; p = []; else dflag = 'linear'; if isempty(P{6}), p = .95; else p = P{6}; end end elseif length(P) == 7 if isempty(P{2}), nfft = min(length(x),256); else nfft=P{2}; end window = P{4}; window = window(:); % force window to be a column if length(window) == 1, window = hanning(window); end if isempty(window), window = hanning(nfft); end if isempty(P{3}), noverlap = 0; else noverlap=P{3}; end if isempty(P{5}), Fs = 2; else Fs = P{5}; end if isempty(P{6}), p = .95; else p = P{6}; end if ischar(P{7}) dflag = P{7}; else error(message('signal:spectrum:NeedStringDFLAG')); end end % NOW do error checking if (nfft<length(window)), error(message('signal:spectrum:WindowTooBig')); end if (noverlap >= length(window)), error(message('signal:spectrum:NOVERLAPTooBig')); end if (nfft ~= abs(round(nfft)))||(noverlap ~= abs(round(noverlap))), error(message('signal:spectrum:NeedPosInts')); end if ~isempty(p), if (numel(p)>1)||(p(1,1)>1)||(p(1,1)<0), error(message('signal:spectrum:StrictlyInsideUnitRange')); end end if min(size(x))~=1, error(message('signal:spectrum:NeedVecInput')); end if (min(size(y))~=1)&&(~isempty(y)), error(message('signal:spectrum:NeedVecInput')); end if (length(x)~=length(y))&&(~isempty(y)), error(message('signal:spectrum:MismatchedDimensions')); end