No BSD License  

Highlights from
filtfilthd

from filtfilthd by Malcolm Lidierth
Zero-phase forwards/backwards filtering using SP toolbox dfilt filter objects

x=filtfilthd(varargin)
function x=filtfilthd(varargin)
% FILTFILTHD Zero-phase digital filtering with dfilt objects.
%
% FILTFILLTHD provides zero phase filtering and accepts dfilt objects on
% input. A number of end-effect minimization methods are supported.
%
% Examples:
% x=FILTFILTHD(Hd, x)
% x=FILTFILTHD(Hd, x, method)
% where Hd is a dfilt object and x is the input data. If x is a matrix,
% each column will be filtered.
%
% ------------------------------------------------------------------------
% The filter states of Hd on entry to FILTFILTHD will be used at the
% beginning of each forward and each backward pass through the data. The 
% user should normally ensure that the initial states are zeroed before
% calling filtfilthd [e.g. using reset(Hd);]
% ------------------------------------------------------------------------
%
% x=FILTFILTHD(b, a, x) 
% x=FILTFILTHD(b, a, x, method)
%           format is also supported.
%
% x=FILTFILTHD(...., IMPULSELENGTH)
%   allows the impulse response length to be specified on input. 
%
%
% method is a string describing the end-effect correction technique:
%   reflect:      data at the ends are reflected and mirrored as in
%                   the MATLAB filtfilt function (default)
%   predict:      data are extraploated using linear prediction
%   spline/pchip: data are extrapolated using MATLAB's interp1 function
%   none:         no internal end-effect correction is applied
%                   (x may be pre-pended and appended with data externally)
%
% Each method has different merits/limitations. The most robust
% method is reflect.
% 
% The length of the padded data section at each end will be impzlength(Hd)
% points, or with 'reflect', the minimum of impzlength(Hd) and the
% data length (this is different to filtfilt where the padding is only
% 3 * the filter width). Using the longer padding reduces the need for any
% DC correction (see the filtfilt documentation).
%
%
% See also: dfilt, filtfilt, impzlength
%
% -------------------------------------------------------------------------
% Author: Malcolm Lidierth 10/07
% Copyright  The Author & King's College London 2007
% -------------------------------------------------------------------------
%
% Revisions:
%   07.11.07    nfact=len-1 (not len) when impulse response longer than
%                           data
%   11.11.07    Use x=f(x) for improved memory performance 
%                           [instead of y=f(x)]
%               Handles row vectors properly
%   31.01.08    Allow impzlength to be specified on input
%                           

% ARGUMENT CHECKS
if isnumeric(varargin{1}) && isnumeric(varargin{2})
    % [b, a] coefficients on input, convert to a singleton filter.
    Hd = dfilt.df2(varargin{1}, varargin{2});
    x=varargin{3};
elseif ~isempty(strfind(class(varargin{1}),'dfilt'))
    % dfilt object on input
    Hd=varargin{1};
    x=varargin{2};
else
    error('Input not recognized');
end

if ischar(varargin{end})
    method=varargin{end};
else
    method='reflect';
end

if isscalar(varargin{end})
    nfact=varargin{end};
else
    nfact=impzlength(Hd);
end

% DEAL WITH MATRIX INPUTS-----------------------------------------------
% Filter each column in turn through recursive calls
[m,n]=size(x);
if (m>1) && (n>1) 
    for i=1:n
        x(:,i)=filtfilthd(Hd, x(:,i), method, nfact);
    end
    return
end

% MAIN FUNCTION-------------------------------------------------------
% Make sure x is a column. Return to row vector later if needed
if m==1
    x = x(:);
    trflag=true;
else
    trflag=false;
end

len=length(x);
switch method
    case 'reflect'
        % This is similar to the MATLAB filtfilt reflect and mirror method
        nfact=min(len-1, nfact);%change to len-1 not len 07.11.07
        pre=2*x(1)-x(nfact+1:-1:2);
        post=2*x(len)-x(len-1:-1:len-nfact);
    case 'predict'
        % Use linear prediction. DC correction with mean(x).
        % Fit over 2*nfact points, with nfact coefficients
        np=2*nfact;
        m=mean(x(1:np));
        pre=lpredict(x(1:np)-m, nfact, nfact, 'pre')+m;
        m=mean(x(end-np+1:end));
        post=lpredict(x(end-np+1:end)-m, nfact, nfact, 'post')+m;
    case {'spline', 'pchip'}
        % Spline/pchip extrapolation.
        % Fit over 2*nfact points,
        np=2*nfact;
        pre=interp1(1:np, x(np:-1:1), np+1:np+nfact, method, 'extrap');
        pre=pre(end:-1:1)';
        post=interp1(1:np, x(end-np+1:end), np+1:np+nfact, method, 'extrap')';
    case 'none'
        % No end-effect correction
        pre=[];
        post=[];
end

% % UNCOMMENT TO VIEW THE PADDED DATA 
% if length(pre);plot(pre,'color', 'r');end;
% line(length(pre)+1:length(pre)+length(x), x);
% if length(post);line(length(pre)+length(x)+1:length(pre)+length(x)+length(post), post, 'color', 'm');end;


% Remember Hd is passed by reference - save entry state and restore later
memflag=get(Hd, 'persistentmemory');
states=get(Hd, 'States');
set(Hd,'persistentmemory', true);

%--------------------------------
% ----- FORWARD FILTER PASS -----
% User-supplied filter states at entry will be applied
% Pre-pended data
pre=filter(Hd, pre); %#ok<NASGU>
% Input data
x=filter(Hd ,x);
% Post-pended data
post=filter(Hd, post);

% ------ REVERSE FILTER PASS -----
% Restore user-supplied filter states for backward pass
set(Hd, 'States', states);
% Post-pended reversed data
post=filter(Hd, post(end:-1:1)); %#ok<NASGU>
% Reversed data
x=filter(Hd, x(end:-1:1));

% Restore data sequence
x=x(end:-1:1);
%---------------------------------
%---------------------------------

% Restore Hd
set(Hd, 'States', states);
set(Hd,'persistentmemory', memflag)

% Revert to row if necessary
if trflag
    x=x.';   
end

return
end


%--------------------------------------------------------------------------
function y=lpredict(x, np, npred, pos)
% LPREDICT estimates the values of a data set before/after the observed
% set.
% LPREDICT Local version. For a stand-alone version see:
% http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=16798&objectType=FILE
% -------------------------------------------------------------------------
% Author: Malcolm Lidierth 10/07
% Copyright  The Author & King's College London 2007
% -------------------------------------------------------------------------
% Order input sequence
if nargin==4 && strcmpi(pos,'pre')
    x=x(end:-1:1);
end
% Get the forward linear predictor coefficients via the LPC
% function
a=lpc(x,np);
% Negate coefficients, and get rid of a(1)
cc=-a(2:end);
% Pre-allocate output
y=zeros(npred,1);
% Seed y with the first value
y(1)=cc*x(end:-1:end-np+1);
% Next np-1 values
for k=2:min(np,npred)
    y(k)=cc*[y(k-1:-1:1); x(end:-1:end-np+k)];
end
% Now do the rest
for k=np+1:npred
    y(k)=cc*y(k-1:-1:k-np);
end
% Order the output sequence if required
if nargin==4 && strcmpi(pos,'pre')
    y=y(end:-1:1);
end
return
end
% -------------------------------------------------------------------------

Contact us at files@mathworks.com