Mercurial > hg > emotion-detection-top-level
diff Code/Descriptors/Matlab/MPEG7/FromWeb/h_specgram2.m @ 4:92ca03a8fa99 tip
Update to ICASSP 2013 benchmark
author | Dawn Black |
---|---|
date | Wed, 13 Feb 2013 11:02:39 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/Descriptors/Matlab/MPEG7/FromWeb/h_specgram2.m Wed Feb 13 11:02:39 2013 +0000 @@ -0,0 +1,163 @@ +function [yo,fo,to] = h_specgram2(varargin) +%SPECGRAM Calculate spectrogram from signal. +% B = SPECGRAM(A,NFFT,Fs,WINDOW,SHIFT) calculates the spectrogram for +% the signal in vector A. SPECGRAM splits the signal into overlapping +% segments, windows each with the WINDOW vector and forms the columns of +% B with their zero-padded, length NFFT discrete Fourier transforms. Thus +% each column of B contains an estimate of the short-term, time-localized +% frequency content of the signal A. Time increases linearly across the +% columns of B, from left to right. Frequency increases linearly down +% the rows, starting at 0. If A is a length NX complex signal, B is a +% complex matrix with NFFT rows and +% k = fix((NX-NOVERLAP)/(length(WINDOW)-NOVERLAP)) +% columns, where NOVERLAP = length(WINDOW)-mean(SHIFT) +% If A is real, B still has k columns but the higher frequency +% components are truncated (because they are redundant); in that case, +% SPECGRAM returns B with NFFT/2+1 rows for NFFT even and (NFFT+1)/2 rows +% for NFFT odd. If you specify a scalar for WINDOW, SPECGRAM uses a +% Hanning window of that length. WINDOW must have length smaller than +% or equal to NFFT and greater than NOVERLAP. NOVERLAP is the number of +% samples the sections of A overlap. Fs is the sampling frequency +% which does not effect the spectrogram but is used for scaling plots. +% +% [B,F,T] = SPECGRAM(A,NFFT,Fs,WINDOW,NOVERLAP) returns a column of +% frequencies F and one of times T at which the spectrogram is computed. +% F has length equal to the number of rows of B, T has length k. If you +% leave Fs unspecified, SPECGRAM assumes a default of 2 Hz. +% +% B = SPECGRAM(A) produces the spectrogram of the signal A using default +% settings; the defaults are NFFT = minimum of 256 and the length of A, a +% Hanning window of length NFFT, and NOVERLAP = length(WINDOW)/2. You +% can tell SPECGRAM to use the default for any parameter by leaving it +% off or using [] for that parameter, e.g. SPECGRAM(A,[],1000) +% +% See also PWELCH, CSD, COHERE and TFE. + +% Author(s): L. Shure, 1-1-91 +% T. Krauss, 4-2-93, updated +% Copyright 1988-2000 The MathWorks, Inc. +% $Revision: 1.6 $ $Date: 2000/06/09 22:07:35 $ + +error(nargchk(1,5,nargin)) +[msg,x,nfft,Fs,window,shift]=specgramchk(varargin); +error(msg) + +nx = length(x); +nwind = length(window); +if nx < nwind % zero-pad x if it has length less than the window length + x(nwind)=0; nx=nwind; +end +x = x(:); % make a column vector for ease later +window = window(:); % be consistent with data set +noverlap = nwind - mean(shift); +ncol = fix((nx-noverlap)/(nwind-noverlap)); + +totalshift = sum(shift); +numshift = length(shift); +progshift = (cumsum(shift)-shift(1))'; +overshift = 1:totalshift:nx; +shifts = progshift(:,ones(1,length(overshift)))+overshift(ones(length(progshift),1),:); +colindex = reshape(shifts,1,prod(size(shifts))); +colindex = colindex(1:ncol); +%colindex = 1 + (0:(ncol-1))*(nwind-noverlap); +rowindex = (1:nwind)'; +if length(x)<(nwind+colindex(ncol)-1) + x(nwind+colindex(ncol)-1) = 0; % zero-pad x +end + +y = zeros(nwind,ncol); + +% put x into columns of y with the proper offset +% should be able to do this with fancy indexing! +y(:) = x(rowindex(:,ones(1,ncol))+colindex(ones(nwind,1),:)-1); + +% Apply the window to the array of offset signal segments. +y = window(:,ones(1,ncol)).*y; + +% now fft y which does the columns +y = fft(y,nfft); +if ~any(any(imag(x))) % x purely real + if rem(nfft,2), % nfft odd + select = [1:(nfft+1)/2]; + else + select = [1:nfft/2+1]; + end + y = y(select,:); +else + select = 1:nfft; +end +f = (select - 1)'*Fs/nfft; + +t = (colindex-1)'/Fs; + +% take abs, and use image to display results +if nargout == 0 +% newplot; +% if length(t)==1 +% imagesc([0 1/f(2)],f,20*log10(abs(y)+eps));axis xy; colormap(jet) +% else +% imagesc(t,f,20*log10(abs(y)+eps));axis xy; colormap(jet) +% end +% xlabel('Time') +% ylabel('Frequency') +elseif nargout == 1, + yo = y; +elseif nargout == 2, + yo = y; + fo = f; +elseif nargout == 3, + yo = y; + fo = f; + to = t; +end + +function [msg,x,nfft,Fs,window,shift] = specgramchk(P) +%SPECGRAMCHK Helper function for SPECGRAM. +% SPECGRAMCHK(P) takes the cell array P and uses each cell as +% an input argument. Assumes P has between 1 and 5 elements. + +msg = []; + +x = P{1}; +if (length(P) > 1) & ~isempty(P{2}) + nfft = P{2}; +else + nfft = min(length(x),256); +end +if (length(P) > 2) & ~isempty(P{3}) + Fs = P{3}; +else + Fs = 2; +end +if length(P) > 3 & ~isempty(P{4}) + window = P{4}; +else + if length(nfft) == 1 + window = hanning(nfft); + else + msg = 'You must specify a window function.'; + end +end +if length(window) == 1, window = hanning(window); end +if (length(P) > 4) & ~isempty(P{5}) + shift = P{5}; +else + shift = ceil(length(window)/2); +end + +% NOW do error checking +if (length(nfft)==1) & (nfft<length(window)), + msg = 'Requires window''s length to be no greater than the FFT length.'; +end +if (min(shift) <= 0), + msg = 'Requires SHIFT to be strictly positive.'; +end +if (length(nfft)==1) & (nfft ~= abs(round(nfft))) + msg = 'Requires positive integer values for NFFT.'; +end +if sum(shift ~= abs(round(shift))), + msg = 'Requires positive integer value for NOVERLAP.'; +end +if min(size(x))~=1, + msg = 'Requires vector (either row or column) input.'; +end