function aQ = lsfpredq( a, lsfdbits )
% function aQ = lsfpredq( a, lsfdbits )
%
% Simulation of Line-Spectral-Frequency Predictor-Coefficients Quantizer: 
% Linear Quantization of LSP Differences
%
% a:        input vector to be quantized
% lsfdbits: vector containing number of bits per LSP difference   
% aQ:       quantized approximation of a
%
% Author:  Markus Hauenstein
% Date:    25.01.2002
% Contact: www.markus-hauenstein.de

a = a(:);
lsfdbits = lsfdbits(:);
N = length(a);

if N ~= length(lsfdbits),
  error( 'lsppredq: a and lsfdbits do not have the same size' );
end


% calculate lsps and lsp differences (coder)

A1 = [1; -a; 0];
A2 = A1([length(A1):-1:1]);
Q1 = A1 + A2;
Q2 = A1 - A2;

lsf1 = angle(roots(Q1));
lsf2 = angle(roots(Q2));
lsf = sort( [ lsf1(find(lsf1>0 & lsf1<pi)); lsf2(find(lsf2>0 & lsf2<pi)) ] );
lsfDiff = [ lsf(1); diff(lsf) ];


% quantize lsp differences (coder)

lsfDiffMax = 1.75*pi/N;
dx = lsfDiffMax./(2.^lsfdbits);
lsfDiffQ = dx .* round(lsfDiff./dx); 


% recalculate quantized predictor coefficients (decoder)

lsfQ = cumsum( lsfDiffQ );

if N/2 - floor(N/2) == 0,
  % even predictor order
  angleRootsQ1Q = [ lsfQ([1:2:N-1]); -lsfQ([1:2:N-1]); pi ];  
  angleRootsQ2Q = [ 0; lsfQ([2:2:N]); -lsfQ([2:2:N]) ]; 
else
  % odd predictor order
  angleRootsQ1Q = [ lsfQ([1:2:N]); -lsfQ([1:2:N])];  
  angleRootsQ2Q = [ 0; lsfQ([2:2:N-1]); -lsfQ([2:2:N-1]); pi ]; 
end

rootsQ1Q = exp( i*angleRootsQ1Q );
rootsQ2Q = exp( i*angleRootsQ2Q );     

Q1Q = poly(rootsQ1Q);
Q2Q = poly(rootsQ2Q);

AQ = real( .5*( Q1Q + Q2Q ) );
aQ = -AQ([2:N+1]);
aQ = aQ(:);

