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 % Undoes the last incrementation 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 % Undoes the last incrementation 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