classdef (CaseInsensitiveProperties=true, TruncatedProperties=true) tf < matlab.mixin.SetGet & matlab.mixin.Copyable
%lwdfilt.tf class
%    lwdfilt.tf properties:
%       Numerator - Property is of type 'mxArray'  
%       Denominator - Property is of type 'mxArray'  
%       refnum - Property is of type 'mxArray'  
%       refden - Property is of type 'mxArray'  
%
%    lwdfilt.tf methods:
%       computefreqz - FREQZ   Calculate the frequency response of the filter.
%       computegrpdelay - GRPDELAY   Calculate the group delay.
%       computeimpz -   Calculate the impulse response.
%       computephasedelay - PHASEDELAY   Calculate the phase delay.
%       computephasez - PHASEZ   Return the phase response.
%       computestepz - STEPZ   Calculate the step response.
%       dispstr - Display string of coefficients.
%       impzlength - Length of the impulse response for a digital filter.
%       reffilter -   Returns the double representation of the filter object.
%       thiscoefficients - Filter coefficients.
%       thisorder - Filter order.
%       thistf -  Convert to transfer function.
%       zpk -  Discrete-time filter zero-pole-gain conversion.


properties (SetObservable)

    %NUMERATOR Property is of type 'mxArray'
    Numerator = 1;
    %DENOMINATOR Property is of type 'mxArray'
    Denominator = 1;
    %REFNUM Property is of type 'mxArray'
    refnum = 1;
    %REFDEN Property is of type 'mxArray'
    refden = 1;
end


methods 
    function this = tf(num, den)
        %TF   Construct a TF object.

        if nargin > 0
            set(this, 'Numerator', num);
            set(this, 'refnum', num);
            if nargin > 1
                set(this, 'Denominator', den);
                set(this, 'refden', den);
            end
        end
    end  % tf

    %----------------------------------------
    function [H, W] = computefreqz(this, N, varargin)
        %FREQZ   Calculate the frequency response of the filter.

        if nargin < 2
            N = 8192;
        end

        [H, W] = freqz(this.Numerator, this.Denominator, N, varargin{:});

    end  % computefreqz

    %----------------------------------------
    function [G, W] = computegrpdelay(this, N, varargin)
        %GRPDELAY   Calculate the group delay.

        if nargin < 2
            N = 8192;
        end

        [G, W] = grpdelay(this.Numerator, this.Denominator, N, varargin{:});

    end  % computegrpdelay

    %----------------------------------------
    function [I, T] = computeimpz(this, varargin)
        %COMPUTEIMPZ   Calculate the impulse response.

        [I, T] = impz(this.Numerator, this.Denominator, varargin{:});

    end  % computeimpz

    %----------------------------------------
    function [P, W] = computephasedelay(this, N, varargin)
        %PHASEDELAY   Calculate the phase delay.

        if nargin < 2
            N = 8192;
        end

        [P, W] = phasedelay(this.Numerator, this.Denominator, N, varargin{:});

    end  % computephasedelay

    %----------------------------------------
    function [P, W] = computephasez(this, N, varargin)
        %PHASEZ   Return the phase response.

        if nargin < 2
            N = 8192;
        end

        [P, W] = phasez(this.Numerator, this.Denominator, N, varargin{:});

    end  % computephasez

    %----------------------------------------
    function [S, T] = computestepz(this, varargin)
        %STEPZ   Calculate the step response.

        [S, T] = stepz(this.Numerator, this.Denominator, varargin{:});

    end  % computestepz

    %----------------------------------------
    function s = dispstr(this, varargin)
        %DISPSTR Display string of coefficients.
        %   DISPSTR(Hd) returns a string that can be used to display the coefficients
        %   of discrete-time filter Hd.

        [num, den] = lcldispstr(this.Numerator(:), this.Denominator(:), varargin{:});

        s = char({getString(message('signal:sigtools:siggui:Numerator'))
            num
            getString(message('signal:sigtools:siggui:Denominator'))
            den
            });
    end  % dispstr

    %----------------------------------------
    function len = impzlength(this, varargin)
        %IMPZLENGTH Length of the impulse response for a digital filter.

        len = impzlength(this.Numerator,this.Denominator,varargin{:});

    end  % impzlength

    %----------------------------------------
    function Hd = reffilter(this)
        %REFFILTER   Returns the double representation of the filter object.

        Hd = lwdfilt.tf;
        Hd.Numerator = this.refnum;
        Hd.refnum = this.refnum;
        Hd.Denominator = this.refden;
        Hd.refden = this.refden;

    end  % reffilter

    %----------------------------------------
    function c = thiscoefficients(Hd)
        %THISCOEFFICIENTS Filter coefficients.
        %   C = THISCOEFFICIENTS(Hd) returns a cell array of coefficients of
        %   discrete-time filter Hd.

        c = {Hd.Numerator, Hd.Denominator};

    end  % thiscoefficients

    %----------------------------------------
    function n = thisorder(Hd)
        %THISORDER Filter order.
        %   THISORDER(Hd) returns the order of filter Hd.

        b = Hd.Numerator;
        a = Hd.Denominator;

        % Converting to statespace may have left some coefficients very near zero
        % because of numerical roundoff.  Remove trailing zeros.

        % Normalize vectors so that there is not a large difference in magnitudes.
        if ~isempty(b) & max(abs(b))~=0
            b = b/max(abs(b));
        end
        if ~isempty(a) & max(abs(a))~=0
            a = a/max(abs(a));
        end

        % Remove trailing "zeros" of a & b.
        if ~isempty(b)
            b = b(1:find(b~=0, 1, 'last' ));
        end
        if ~isempty(a)
            a = a(1:find(a~=0, 1, 'last' ));
        end

        n = max(length(b),length(a)) - 1;

    end  % thisorder

    %----------------------------------------
    function [num,den] = thistf(Hd)
        %THISTF  Convert to transfer function.
        %   [NUM,DEN] = THISTF(Hd) converts discrete-time filter Hd to numerator and
        %   denominator vectors.

        num = Hd.Numerator;
        den = Hd.Denominator;

    end  % thistf

    %----------------------------------------
    function [z,p,k] = zpk(this)
        %ZPK  Discrete-time filter zero-pole-gain conversion.

        [z,p,k] = tf2zpk(this.Numerator,this.Denominator);

    end  % zpk

    %----------------------------------------
    function [hz, wz, phiz, opts] = computezerophase(this, N, varargin)
        %COMPUTEZEROPHASE

        if nargin < 2
            N = 8192;
        end

        [hz,wz,phiz,opts] = zerophase(this.Numerator,this.Denominator,N,varargin{:});


    end  % computezerophase

end 
end  % classdef

%--------------------------------------------------------------------------
function varargout = lcldispstr(varargin)

% Ignore the format, can only work fixed.
if ischar(varargin{end})
    fmt = varargin{end};
    varargin(end) = [];
else
    fmt = 'dec';
end

switch lower(fmt(1:3))
    case 'dec'
        for indx = 1:length(varargin)
            varargout{indx} = signal_num2str(varargin{indx}); %#ok<*AGROW>
        end
    case 'hex'
        for indx = 1:length(varargin)
            [rows, cols] = size(varargin{indx});
            if cols > 1 && rows > 1
                str = [];
                for jndx = 1:cols
                    str = [str repmat('  ', rows, 1) num2hex(varargin{indx}(:,jndx))];
                end
                str(:, 1:2) = [];
            else
                str = num2hex(varargin{indx});
            end
            varargout{indx} = str;
        end
    case 'bin'
        if isfixptinstalled
            q = quantizer('double');
            for indx = 1:length(varargin)
                [rows, cols] = size(varargin{indx});
                if cols > 1 && rows > 1
                    str = [];
                    for jndx = 1:cols
                        str = [str repmat('  ', rows, 1) num2bin(q, varargin{indx}(:,jndx))];
                    end
                    str(:, 1:2) = [];
                else
                    str = num2bin(q, varargin{indx});
                end
                varargout{indx} = str;
            end
        else
            error(message('signal:lwdfilt:tf:dispstr:invalidFormat'));
        end
end
end  % lcldispstr


