Code covered by the BSD License  

Highlights from
FIRQUEST

image thumbnail

FIRQUEST

by

 

07 Apr 2008 (Updated )

FIRQUEST optimizes the quantization of FIR coefficients.

b2=firquest(n,ns,Fp,Fst,Ast,W,N)
% FIRQUEST Generate lowpass FIR filter with quantized coefficients
% Usage:
%   b = FIRQUEST(n,ns,Fp,Fst,Ast,W,N) 
% Arguments:
%   n   Lowpass Filter order 
%   ns  Shaping Filter order
%   Fp  passband frequency (normalized to Nyquist)
%   Fst stopband frequency (normalized to Nyquist)
%   Ast stopband suppression (dB)
%   W   coefficient word size in bits
%   N   fft size (defaults to 1024)
% Return values:
%   b   quantized filter coefficients
% Example:
%   b=firquest(37,6,0.3,0.6,16,120,1024);
%   fvtool(b,1);
% Based on:
%   J.J. Nielsen, 'Design of Linear-Phase Direct-Form FIR Digital Filters 
%   with Quantized Coefficients Using Error Spectrum Shaping Techniques', 
%   IEEE Transactions on Acoustics, Speech and Signal Processing, 
%   vol. ASSP-37, pp. 1020-1026, july 1989.

function b2=firquest(n,ns,Fp,Fst,Ast,W,N)

% default values
if ~exist('n'  ,'var');  n=37;       end
if ~exist('ns' ,'var');  ns=6;       end
if ~exist('Fp' ,'var');  Fp=0.3;     end
if ~exist('Fst','var');  Fst=0.6;    end
if ~exist('q'  ,'var');  W=16;       end
if ~exist('Ast','var');  Ast=W*6+40; end
if ~exist('N'  ,'var');  N=1024;     end

% design the lowpass filter
fd=fdesign.lowpass('n,fp,fst,ast',n,Fp,Fst,Ast);
d=design(fd,'equiripple');
b0=d.Numerator;

% design the shaping filter
dp=1E-1;
ds=1E-2;
bb=fircls1(ns,(Fp+Fst)/2,dp,ds,Fp,Fst,1E4);

%fd=fdesign.lowpass('n,fp,fst',3,Fp,Fst);
%d=design(fd,'equiripple');
%bb=d.Numerator;

% determine the stopband indices
f=linspace(0,2*(N-1)/N,N);
ist=find(f>Fst & f<1);

% rescaling
r=2^(W-1);
b0=r*b0/max(abs(b0))*(r-10)/r;
s=sum(b0);

% normal rounding
b1=round(b0);
y1=firquest_eval(b1,N,ist,s);
b2=b1;
y2=y1;
for i=1:10000
    bt=firquest_shape(bb,b0);
    y=firquest_eval(bt,N,ist,s);
    if y<y2 
        y2=y;
        b2=bt;
        display(sprintf('%5i %7.2f %5.2f',i,y2,y1-y2));
    end
end


if nargout==0
  h_bb=freqz(bb/bb(1),1,pi*f);
  h_b0=freqz(b0/s    ,1,pi*f);
  h_b1=freqz(b1/s    ,1,pi*f);
  h_b2=freqz(b2/s    ,1,pi*f);

  figure(1);
  plot(f,20*log10(abs([h_b1;h_b2;h_b0])));
  axis([0 1 -200 50]);
  grid on;
  title('Magnitude Response');
  xlabel('Normalized Frequency');
  ylabel('Magnitude (dB)');
  legend( 'round', 'shaped', 'unquantized');

  figure(2)
  plot(f,20*log10(abs([h_b1-h_b0;h_b2-h_b0;h_bb])));
  axis([0 1 -200 50]);
  grid on;
  title('Error Response');
  xlabel('Normalized Frequency');
  ylabel('Error (dB)');
  legend('round', 'shaped', 'shaping filter');
  clear b2
end

% evaluate filter performance by finding the max stopband level
function y=firquest_eval(bt,N,ist,s)
bf=fft([bt zeros(1,N-length(bt))]);
bst=bf(ist);
y=10*log10(max(bst.*conj(bst))/(s*s));

% generate a shaped filter, using the error spectral shaping technique
function z=firquest_shape(b,x)
L=length(x);
% even and odd lengths are treated seperately
if mod(L,2)==0
    x=x((L+2)/2:L);
else
    x=x((L+1)/2:L);
end

b=b/b(1);
b=b(2:length(b));
y=(rand(size(b))-0.5);
z=zeros(size(b));
for i=1:length(x)
    y0=sum(b.*y)+x(i);
    yr=round(y0);    
    z(i)=yr;
    y=[yr-y0 y(1:length(y)-1)];
end
if mod(L,2)==0 
    z=[fliplr(z) z];
else
    z=[fliplr(z) z(2:length(z))];
end      

Contact us