|
|
|
function [S, sfc, G] = AACquantizer(frameF, frameType, SMR)
|
|
|
|
%Implementation of Quantizer
|
|
|
|
% Usage [S, sfc, G] = AACquantizer(frameF, frameType, SMR), where:
|
|
|
|
% Inputs
|
|
|
|
% - frameF is the frame in the frequency domain, in MDCT coefficients
|
|
|
|
% representation containing only one of the audio channels stored in
|
|
|
|
% a vector of length 1024
|
|
|
|
% - frameType is the type of the current frame in string
|
|
|
|
% representation, can be one of "OLS" (ONLY_LONG_SEQUENCE), "LSS"
|
|
|
|
% (LONG_START_SEQUENCE), "ESH" (EIGHT_SHORT_SEQUENCE), "LPS"
|
|
|
|
% (LONG_STOP_SEQUENCE)
|
|
|
|
% - SMR is the signal to mask ratio array of dimensions 42X8 for
|
|
|
|
% EIGHT_SHORT_SEQUENCE frames and 69X1 otherwise
|
|
|
|
%
|
|
|
|
% Output
|
|
|
|
% - S are the MDCT quantization symbols of one audio channel stored
|
|
|
|
% in a vector of length 1024
|
|
|
|
% - sfc are the scalefactors per band stored in an array of
|
|
|
|
% dimensions NBX8 for EIGHT_SHORT_SEQUENCE frames and NBX1
|
|
|
|
% otherwise, where NB is the number of bands
|
|
|
|
% - G is the global gain stored in an array of dimensions 1X8 for
|
|
|
|
% EIGHT_SHORT_SEQUENCE frames and a single value otherwise
|
|
|
|
|
|
|
|
% Declares constant numbers of bands for long and short windows
|
|
|
|
LONG_WINDOW_NUMBER_OF_BANDS = 69;
|
|
|
|
SHORT_WINDOW_NUMBER_OF_BANDS = 42;
|
|
|
|
|
|
|
|
% Declares persistent variable holding the TNS tables and initializes if empty
|
|
|
|
persistent TNSTables;
|
|
|
|
if isempty(TNSTables)
|
|
|
|
TNSTables = load('TableB219.mat');
|
|
|
|
end
|
|
|
|
|
|
|
|
if ~strcmp(frameType, 'ESH')
|
|
|
|
T(LONG_WINDOW_NUMBER_OF_BANDS, 1) = 0;
|
|
|
|
quantCoeff(LONG_WINDOW_NUMBER_OF_BANDS, 1) = 0;
|
|
|
|
sfc(LONG_WINDOW_NUMBER_OF_BANDS, 1) = 0;
|
|
|
|
initialQuantCoeff = 16 * log2(max(frameF) ^ (3 / 4) / 8191) / 3;
|
|
|
|
for band = 1:LONG_WINDOW_NUMBER_OF_BANDS
|
|
|
|
frameWlow = TNSTables.B219a(band, 2) + 1;
|
|
|
|
frameWhigh = TNSTables.B219a(band, 3) + 1;
|
|
|
|
subFrameF = frameF(frameWlow:frameWhigh);
|
|
|
|
|
|
|
|
T(band) = sumsqr(subFrameF) ./ SMR(band);
|
|
|
|
|
|
|
|
% Calculates an initial quantization coefficient and attempts
|
|
|
|
% quantization
|
|
|
|
quantCoeff(band) = initialQuantCoeff;
|
|
|
|
S(frameWlow:frameWhigh, 1) = sign(subFrameF) .* floor(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
|
|
|
|
% Calculates dequantized frame samples
|
|
|
|
frameFDequant = sign(S(frameWlow:frameWhigh, 1)) .* ...
|
|
|
|
abs(S(frameWlow:frameWhigh, 1)) .^ ...
|
|
|
|
(4 / 3) .* 2 ^ (quantCoeff(band) / 4);
|
|
|
|
|
|
|
|
% Calculates current quantization error
|
|
|
|
quantErr = sumsqr(subFrameF - frameFDequant);
|
|
|
|
|
|
|
|
% Gradually increases the quantization coefficient
|
|
|
|
while quantErr < T(band) && (band < 2 || ...
|
|
|
|
(quantCoeff(band) - quantCoeff(band - 1) + 1) <= 60)
|
|
|
|
quantCoeff(band) = quantCoeff(band) + 1;
|
|
|
|
S(frameWlow:frameWhigh) = sign(subFrameF) .* round(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
|
|
|
|
frameFDequant = sign(S(frameWlow:frameWhigh, 1)) .* ...
|
|
|
|
abs(S(frameWlow:frameWhigh, 1)) .^ ...
|
|
|
|
(4 / 3) .* 2 ^ (quantCoeff(band) / 4);
|
|
|
|
|
|
|
|
quantErr = sumsqr(subFrameF - frameFDequant);
|
|
|
|
end
|
|
|
|
|
|
|
|
if quantCoeff(band) ~= initialQuantCoeff
|
|
|
|
quantCoeff(band) = quantCoeff(band) - 1;
|
|
|
|
S(frameWlow:frameWhigh) = sign(subFrameF) .* round(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
end
|
|
|
|
|
|
|
|
if band == 1
|
|
|
|
sfc(band) = quantCoeff(band);
|
|
|
|
else
|
|
|
|
sfc(band) = quantCoeff(band) - quantCoeff(band - 1);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
G = quantCoeff(1);
|
|
|
|
else
|
|
|
|
T(SHORT_WINDOW_NUMBER_OF_BANDS, 1) = 0;
|
|
|
|
quantCoeff(SHORT_WINDOW_NUMBER_OF_BANDS, 1) = 0;
|
|
|
|
sfc(SHORT_WINDOW_NUMBER_OF_BANDS, 8) = 0;
|
|
|
|
G(1, 8) = 0;
|
|
|
|
for subFrameIndex = 1:8
|
|
|
|
currFrameStart = (subFrameIndex - 1) * 128 + 1;
|
|
|
|
currFrameStop = currFrameStart + 127;
|
|
|
|
subFrame = frameF(currFrameStart:currFrameStop);
|
|
|
|
initialQuantCoeff = 16 * log2(max(subFrame) ^ (3 / 4) / 8191) / 3;
|
|
|
|
for band = 1:SHORT_WINDOW_NUMBER_OF_BANDS
|
|
|
|
frameWlow = TNSTables.B219b(band, 2);
|
|
|
|
frameWhigh = TNSTables.B219b(band, 3);
|
|
|
|
subFrameF = subFrame(frameWlow + 1:frameWhigh + 1);
|
|
|
|
|
|
|
|
T(band) = sumsqr(subFrameF) ./ SMR(band);
|
|
|
|
|
|
|
|
% Calculates an initial quantization coefficient and attempts
|
|
|
|
% quantization
|
|
|
|
quantCoeff(band) = initialQuantCoeff;
|
|
|
|
S(currFrameStart + frameWlow:currFrameStart + frameWhigh, 1) = sign(subFrameF) .* floor(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
|
|
|
|
% Calculates dequantized frame samples
|
|
|
|
frameFDequant = sign(S(currFrameStart + frameWlow: ...
|
|
|
|
currFrameStart + frameWhigh, 1)) .* abs(S( ...
|
|
|
|
currFrameStart + frameWlow:currFrameStart + frameWhigh, 1) ...
|
|
|
|
) .^ (4 / 3) .* 2 ^ (quantCoeff(band) / 4);
|
|
|
|
|
|
|
|
% Calculates current quantization error
|
|
|
|
quantErr = sumsqr(subFrameF - frameFDequant);
|
|
|
|
|
|
|
|
% Gradually increases the quantization coefficient
|
|
|
|
while quantErr < T(band) && (band < 2 || ...
|
|
|
|
(quantCoeff(band) - quantCoeff(band - 1) + 1) <= 60)
|
|
|
|
quantCoeff(band) = quantCoeff(band) + 1;
|
|
|
|
S(currFrameStart + frameWlow:currFrameStart + frameWhigh) = sign(subFrameF) .* round(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
|
|
|
|
frameFDequant = sign(S(currFrameStart + frameWlow: ...
|
|
|
|
currFrameStart + frameWhigh, 1)) .* abs(S( ...
|
|
|
|
currFrameStart + frameWlow:currFrameStart + frameWhigh, 1) ...
|
|
|
|
) .^ (4 / 3) .* 2 ^ (quantCoeff(band) / 4);
|
|
|
|
|
|
|
|
quantErr = sumsqr(subFrameF - frameFDequant);
|
|
|
|
end
|
|
|
|
|
|
|
|
if quantCoeff(band) ~= initialQuantCoeff
|
|
|
|
quantCoeff(band) = quantCoeff(band) - 1;
|
|
|
|
S(currFrameStart + frameWlow:currFrameStart + frameWhigh) = sign(subFrameF) .* round(( ...
|
|
|
|
abs(subFrameF) .* 2 ^ (-quantCoeff(band) / 4)) ...
|
|
|
|
.^ (3 / 4) + 0.4054);
|
|
|
|
end
|
|
|
|
|
|
|
|
if band == 1
|
|
|
|
sfc(band, subFrameIndex) = quantCoeff(band);
|
|
|
|
else
|
|
|
|
sfc(band, subFrameIndex) = quantCoeff(band) - quantCoeff(band - 1);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
G(1, subFrameIndex) = quantCoeff(1);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|