⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fdbutter.m

📁 matlabDigitalSigalProcess内有文件若干
💻 M
📖 第 1 页 / 共 4 页
字号:
function varargout = fdbutter(varargin)
%fdbutter  Butterworth Module for filtdes.

%   Author: T. Krauss
%   Copyright (c) 1988-98 by The MathWorks, Inc.
%   $Revision: 1.7 $

% Change this global to static when available:
%  following are common to several modules
global minOrdCheckbox bandpop order pbspecs sbspecs pbmeasures sbmeasures
global passframe stopframe passframe1 stopframe1
%  following static to fdbutter
global f1 f2 f3 f4 w3db1 w3db2 Rp Rs 
global Rpm w3db1m w3db2m 
global order0 order1
global ax L1 L2 Lresp L3db1 L3db2
global Fs

switch varargin{1}
case 'init'

    filt = varargin{2};
    Fs = filt.Fs;
    [setOrderFlag_init, type_init, f_init, Rp_init, Rs_init, ...
      order_init, w3db_init] = initSpecs(filt);
      
    [minOrdCheckbox bandpop order pbspecs sbspecs ...
         pbmeasures sbmeasures passframe stopframe ...
         passframe1 stopframe1 ax Lresp L1 L2 order1 ...
         L3db1 L3db2] = fdutil('commonObjects');
    order0 = order;
             
    if ~strcmp(bandpop.userdata,'fdbutter')
       % this module is not current
        bandpop.userdata = 'fdbutter';
            
        minOrdCheckbox.callback = 'fdbutter(''checkbox'')';
        bandpop.callback = 'fdbutter(''newtype'')';         

        order0.callback = 'fdbutter(''dirty'')';
                
        f3 = pbspecs(2);
        f4 = sbspecs(2);
        Rp = pbspecs(3);
        Rs = sbspecs(3);
        w3db1 = pbspecs(1);
        w3db2 = sbspecs(2);
        w3dbm1 = sbmeasures(1);
        w3dbm2 = sbmeasures(2);
        
        Rpm = pbmeasures(3);
        
        set(ax,'title','Frequency Response',...
              'xlabel','Frequency',...
              'ylabel','Magnitude (dB)',...
              'ylim',[-150 10],'xlim',[0 Fs/2],...
              'xlimbound',[0 Fs/2]);

        sethelp

        
        set(Lresp,'buttondownfcn','fdbutter(''LrespDown'')')
                       
        set(L1,'buttondownfcn','fdbutter(''L1down'')',...
               'buttonupfcn','fdbutter(''L1up'')');
    
        set(L2,'buttondownfcn','fdbutter(''L2down'')',...
               'buttonupfcn','fdbutter(''L2up'')');
               
        set(L3db1,'xdata',w3db_init([1 1]),...
                  'segmentdragcallback',{'fdbutter(''3db_drag'',1)'},...
                  'buttondownfcn','fdbutter(''3db_down'',1)',...
                  'buttonupfcn','fdbutter(''L1up'')');
                  
        set(L3db2,'xdata',w3db_init([end end]),...
                  'segmentdragcallback',{'fdbutter(''3db_drag'',2)'},...
                  'buttondownfcn','fdbutter(''3db_down'',2)',...
                  'buttonupfcn','fdbutter(''L1up'')');
    end
    set(minOrdCheckbox,'visible','on')
    set(pbspecs(1),'visible','on')
    
    fdbutter('newfilt',setOrderFlag_init,type_init,f_init,Rp_init,...
               Rs_init,w3db_init,order_init)
               
    if setOrderFlag_init
    % set these fields since 'Apply' gets them from the specifications struc
    % to make the measurements
        filt.specs.fdbutter.Rp = Rp_init;
        filt.specs.fdbutter.Rs = Rs_init;
    end
    
    [filt, errstr] = fdutil('callModuleApply',...
                               'fdbutter',filt,'');
                               
    varargout{1} = filt;
    varargout{2} = errstr;

case 'apply'    
    
    filt = varargin{2};
    msg = varargin{3};
    if strcmp(msg,'motion') | strcmp(msg,'up')
        inputLine = varargin{4};
        if ~minOrdCheckbox.value & (isequal(inputLine,L1) | isequal(inputLine,L2))
            varargout{1} = filt;
            varargout{2} = '';
            return
        end
    end
    if strcmp(msg,'motion') & ~strcmp(get(Lresp,'erasemode'),'xor')
        Lresp.erasemode = 'xor';
        drawnow
    end
    
    % DESIGN FILTER!!!!
    type = bandpop.value;
    setOrderFlag = ~minOrdCheckbox.value;
    if ~setOrderFlag     % estimate order
        [n,w3db] = estimateOrder(type,Rp.value,Rs.value,Fs,...
                 f1.value,f2.value,f3.value,f4.value);
    else
        n = order.value;
        w3db = w3db1.value * 2/Fs;
        if type > 2  % pass/stop
            w3db(2) = w3db2.value * 2/Fs;
        end
    end
    
    % save specifications in specifications structure:
    specstruc.setOrderFlag = setOrderFlag;
    specstruc.type = type;
    if ~setOrderFlag
        f = getFrequencyValues(type,f1,f2,f3,f4,Fs);
        specstruc.f = f;
        specstruc.Rp = Rp.value;
        specstruc.Rs = Rs.value;
    else
        specstruc.f = [];  % place holder, will be defined by measureFilt
        specstruc.Rp = filt.specs.fdbutter.Rp;
        specstruc.Rs = filt.specs.fdbutter.Rs;
    end
    specstruc.w3db = w3db;
    specstruc.order = n;
                          
%     if ~setOrderFlag & isfield(filt.specs,'fdbutter') & ...
%         isequal(specstruc.w3db,filt.specs.fdbutter.w3db) ...
%         & isequal(specstruc.order,filt.specs.fdbutter.order)
%         filt.specs.fdbutter = specstruc;
%         varargout{1} = filt;
%         varargout{2} = '';
%         return
%     end
    if n>50
        [continueFlag,errstr] = fdutil('largeWarning',n,msg);
        if ~continueFlag
            varargout{1} = filt;
            varargout{2} = errstr;
            return
        end
    end
    
    % design filter:
    if type == 2
        [b,a] = butter(n,w3db,'high');
    elseif type == 4
        [b,a] = butter(n,w3db,'stop');
    else
        [b,a] = butter(n,w3db);
    end
        
    % compute frequency response:
    nfft = filtdes('nfft');
    [H,ff] = freqz(b,a,nfft,Fs);
    % avoid log of 0 at 0 and Fs/2:
    if H(1) == 0, H(1) = H(2); end
    if H(end) == 0, H(end) = H(end-1); end
    Hlog = 20*log10(abs(H(:)));
    set(Lresp,'xdata',ff,'ydata',Hlog);
    
    % make measurements:
    if ~ ((strcmp(msg,'motion') | strcmp(msg,'up')) & ~setOrderFlag ...
             & strcmp(get(order1,'visible'),'on') )  | ...
       (~setOrderFlag & (filt.specs.fdbutter.type ~= type))
        objSetupFlag = 1;
    else
        objSetupFlag = 0;
    end
    
    [Rp,Rs,w3db1m,w3db2m,Rpm,f1,f2,f3,f4,specstruc] = ...
      measureFilt(objSetupFlag,specstruc,Fs,order,order1,stopframe1,ax,...
                  pbmeasures,sbmeasures,Rp,Rs,w3db1m,w3db2m,Rpm,f1,f2,f3,f4,...
                  ff,Hlog,L1,L2);
                      
    if ~strcmp(msg,'motion')
        % if design is due to a drag operation, lines are already solid
        % so we can skip this step
        Lresp.linestyle = '-';
        L1.linestyle = '-';
        L2.linestyle = '-';
        set(L3db1,'linestyle','-')
        set(L3db2,'linestyle','-')
        if strcmp(L3db1.erasemode,'normal')
            warning('L3db1 erasemode is normal... why?')
            L3db1.erasemode = 'xor';
            L3db2.erasemode = 'xor';
        end
    end
    
    % alter filt fields:
    filt.tf.num = b;
    filt.tf.den = a;
    filt.specs.fdbutter = specstruc;
    filt.zpk = [];  % clear out in case filtview has written these
    filt.ss = [];
    filt.sos = [];

    varargout{1} = filt;
    varargout{2} = '';
        
case 'revert'
    filt = filtdes('filt');
    oldtype = filt.specs.fdbutter.type;
    % need to restore filter type
    setOrderFlag = filt.specs.fdbutter.setOrderFlag;
    oldSetOrderFlag = ~minOrdCheckbox.value;
    f = filt.specs.fdbutter.f;
    Rpass = filt.specs.fdbutter.Rp;
    Rstop = filt.specs.fdbutter.Rs;
    w3db = filt.specs.fdbutter.w3db;
    N = filt.specs.fdbutter.order;
    fdbutter('newfilt',setOrderFlag,oldtype,f,Rpass,Rstop,w3db,N)

    [Rp,Rs,w3db1m,w3db2m,Rpm,f1,f2,f3,f4] = ...
      measureFilt(1,...
                  filt.specs.fdbutter,Fs,order,order1,stopframe1,ax,...
                  pbmeasures,sbmeasures,Rp,Rs,w3db1m,w3db2m,Rpm,f1,f2,f3,f4,...
                  Lresp.xdata,Lresp.ydata,L1,L2);    
    
    Lresp.linestyle = '-';
    L1.linestyle = '-';
    L2.linestyle = '-';
    set(L3db1,'linestyle','-')
    set(L3db2,'linestyle','-')
    
    for i=1:3
        set(pbmeasures(i),'enable','on')
        set(sbmeasures(i),'enable','on')
    end
    set(order1,'enable','on')
    
case 'help'
    str = fdhelpstr('fdbutter');
    varargout{1} = str{2};

case 'description'
    varargout{1} = 'Butterworth IIR';

case 'Fs'
% Sampling frequency has changed

%   The filter spec does not depend on the sampling frequency
    filt = varargin{2};
    varargout{1} = filt;
    
% update various lines and specifications:
    oldFs = varargin{3};
    Fs = filt.Fs;  % new Fs
    f1.value = f1.value*Fs/oldFs;
    f2.value = f2.value*Fs/oldFs;
    f3.value = f3.value*Fs/oldFs;
    f4.value = f4.value*Fs/oldFs;
    f1.range = f1.range*Fs/oldFs;
    f2.range = f2.range*Fs/oldFs;
    f3.range = f3.range*Fs/oldFs;
    f4.range = f4.range*Fs/oldFs;

    ax.xlimbound = [0 Fs/2];
    ax.xlim = ax.xlim*Fs/oldFs;
    ax.xlimpassband = ax.xlimpassband*Fs/oldFs;
    L1.xdata = L1.xdata*Fs/oldFs;
    L2.xdata = L2.xdata*Fs/oldFs;
    Lresp.xdata = Lresp.xdata*Fs/oldFs;
    L3db1.xdata = L3db1.xdata*Fs/oldFs;
    L3db2.xdata = L3db2.xdata*Fs/oldFs;
    
    if minOrdCheckbox.value
        w3db1m.value = w3db1m.value*Fs/oldFs;
        w3db2m.value = w3db2m.value*Fs/oldFs;
    elseif ~any(w3db1==[f1 f2 f3 f4])
        w3db1.value = w3db1.value*Fs/oldFs;
        w3db2.value = w3db2.value*Fs/oldFs;
        w3db1.range = w3db1.range*Fs/oldFs;
        w3db2.range = w3db2.range*Fs/oldFs;
    end
    
%---------------------------------------------------------------------
% -------- following cases are module specific --------- 
%---------------------------------------------------------------------

case 'dirty'
% fdbutter('dirty')
% Callback of a spec ... to change appearance so user can
%  see that the specs and the currently designed filter
%  don't match
    if Lresp.linestyle ~= ':'
        Lresp.linestyle = ':';
        L1.linestyle = ':';
        L2.linestyle = ':';
        L3db1.linestyle = ':';
        L3db2.linestyle = ':';
    end
    for i=1:3
        set(pbmeasures(i),'enable','off')
        set(sbmeasures(i),'enable','off')
    end
    set(order1,'enable','off')

%---------------------------------------------------------------------
% fdbutter('clean')
% opposite of 'dirty'
case 'clean'
    if Lresp.linestyle ~= '-'
        Lresp.linestyle = '-';
        L1.linestyle = '-';
        L2.linestyle = '-';
        L3db1.linestyle = '-';
        L3db2.linestyle = '-';
    end
    for i=1:3
        set(pbmeasures(i),'enable','on')
        set(sbmeasures(i),'enable','on')
    end
    set(order1,'enable','on')
    filtdes('setenable','off')
    
%---------------------------------------------------------------------
% fdbutter('fchange',i)
%    Callback when frequency i has changed
%    Need to update ranges and lines L1, L2
% fdbutter('fchange')
%    called w/o input i when a 3db frequency spec has 
%    changed (in case ~minOrdCheckbox.val==1)
case 'fchange'
    type = bandpop.value;
    if nargin == 1
    % a 3db freq spec has changed  (we are in set mode)
        
        if type >= 3
            w3db = [w3db1.value w3db2.value];
            set(L3db1,'xdata',w3db([1 1]))
            set(L3db2,'xdata',w3db([2 2]))
            w3db1.range = [0 w3db(2)];
            w3db2.range = [w3db(1) Fs/2];
        else
            w3db = w3db1.value;
            set(L3db1,'xdata',w3db([1 1]))
        end
        fdbutter('dirty')
        return
    end
    i = varargin{2};
    xd1 = L1.xdata;
    xd2 = L2.xdata;
    f = [f1.value,f2.value,f3.value,f4.value];
    % update lines
    switch type
    case 1
      % L1 xdata = [0 f1 NaN 0 f1]
      % L2 xdata = [f2 Fs/2]
        if i==1
            xd1([2 5]) = f(1);
        else
            xd2(1) = f(2);
        end
    case 2
      % L1 xdata = [f2 Fs/2 NaN f2 Fs/2]
      % L2 xdata = [0 f1]
        if i == 1
            xd2(2) = f(1);
        else
            xd1([1 4]) = f(2);
        end
    case 3  % bandpass
      % L1 xdata = [f2 f3 NaN f2 f3]
      % L2 xdata = [0 f1 NaN f4 Fs/2]
        if xd2(2) ~= f(1)
            xd2(2) = f(1);
        elseif xd1(1) ~= f(2)
            xd1([1 4]) = f(2);
        elseif xd1(2) ~= f(3)
            xd1([2 5]) = f(3);
        elseif xd2(4) ~= f(4)
            xd2(4) = f(4);
        end
    case 4
      % L1 xdata = [0 f1 NaN 0 f1 NaN f4 Fs/2 NaN f4 Fs/2]
      % L2 xdata = [f2 f3]
        if xd1(2) ~= f(1)
            xd1([2 5]) = f(1);
        elseif xd2(1) ~= f(2)
            xd2(1) = f(2);
        elseif xd2(2) ~= f(3)
            xd2(2) = f(3);
        elseif xd1(7) ~= f(4)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -