Semester assignment for the course "Multimedia systems and virtual reality" of THMMY in AUTH university.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
8.3 KiB

6 years ago
function [frameFout, TNScoeffs] = TNS(frameFin, frameType)
%Implementation of the TNS step
% Usage [frameFout, TNScoeffs] = TNS(frameFin, frameType), where:
% Inputs
% - frameFin is the frame in the frequency domain, in MDCT coefficients
% representation containing both channels of the audio stored in an
% array of dimensions 1024X2
% - 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)
%
% Output
% - frameFout is the frame in the frequency domain after Temporal Noise
% Shaping, in MDCT coefficients representation containing both channels
% of the audio stored in an array of dimensions 1024X2
% - TNScoeffs is the quantized TNS coefficients array of dimensions
% 4X8 for EIGHT_SHORT_SEQUENCE frames and 4X1 otherwise
% Declares constant numbers of bands for long and short windows
LONG_WINDOW_NUMBER_OF_BANDS = 69;
SHORT_WINDOW_NUMBER_OF_BANDS = 42;
% Declares constant order of the linear prediction filter
LPF_ORDER = 4;
% Declares constant coefficients' resolution
COEF_RES = 4;
% 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')
% Calculates the energy per band
bandEnergy(LONG_WINDOW_NUMBER_OF_BANDS) = 0;
for band = 1:LONG_WINDOW_NUMBER_OF_BANDS - 1
bandEnergy(band) = sumsqr(frameFin(TNSTables.B219a(band, 2) + 1:TNSTables.B219a(band + 1, 2)));
end
bandEnergy(LONG_WINDOW_NUMBER_OF_BANDS) = sumsqr( ...
frameFin(TNSTables.B219a(LONG_WINDOW_NUMBER_OF_BANDS, 2) + 1:...
TNSTables.B219a(LONG_WINDOW_NUMBER_OF_BANDS, 3) + 1));
% Calculates the normalization factors
% PROBABLY WRONG, THE ONE BELLOW SHOULD BE RIGHT AND BETTER
% normalizationFactor(1024) = 0;
% for normIndex = 1:1024
% bandIndices = find(TNSTables.B219a(:, 2) >= (normIndex - 1), 1);
% if ~isempty(bandIndices)
% normalizationFactor(normIndex) = sqrt(bandEnergy(bandIndices));
% else
% normalizationFactor(normIndex) = sqrt(bandEnergy(find(TNSTables.B219a(:, 3) >= normIndex - 1, 1)));
% end
% end
bandIndices = quantiz(0:1023, TNSTables.B219a(:, 2) - 1);
normalizationFactor = sqrt(bandEnergy(bandIndices));
% Smooths normalization factors
for normIndex = 1023:-1:1
normalizationFactor(normIndex) = (normalizationFactor(normIndex) + normalizationFactor(normIndex + 1)) / 2;
end
for normIndex = 2:1024
normalizationFactor(normIndex) = (normalizationFactor(normIndex) + normalizationFactor(normIndex - 1)) / 2;
end
% Normalizes MDCT coefficients according to each band energy
normalizedFrameFin = frameFin ./ normalizationFactor';
% Calculates the linear prediction coefficients
[linPredCoeff, ~] = lpc(normalizedFrameFin, LPF_ORDER);
% Quantizes these coefficients
quantizedLinPredCoeff(LPF_ORDER) = 0;
for coeffIndex = 2:length(linPredCoeff)
quantizedLinPredCoeff(coeffIndex - 1) = asin(linPredCoeff(coeffIndex));
if linPredCoeff(coeffIndex) >= 0
quantizedLinPredCoeff(coeffIndex - 1) = round(quantizedLinPredCoeff(coeffIndex - 1) * ...
(bitshift(1, COEF_RES - 1) - 0.5) / (pi / 2));
quantizedLinPredCoeff(coeffIndex - 1) = quantizedLinPredCoeff(coeffIndex - 1) / ...
(bitshift(1, COEF_RES - 1) - 0.5) / (pi / 2);
quantizedLinPredCoeff(coeffIndex - 1) = sin (quantizedLinPredCoeff(coeffIndex - 1));
else
quantizedLinPredCoeff(coeffIndex - 1) = round(quantizedLinPredCoeff(coeffIndex - 1) * ...
(bitshift(1, COEF_RES - 1) + 0.5) / (pi / 2));
quantizedLinPredCoeff(coeffIndex - 1) = quantizedLinPredCoeff(coeffIndex - 1) / ...
(bitshift(1, COEF_RES - 1) + 0.5) / (pi / 2);
quantizedLinPredCoeff(coeffIndex - 1) = sin (quantizedLinPredCoeff(coeffIndex - 1));
end
end
% Filters MDCT coefficients
if ~isstable(1, [1 (quantizedLinPredCoeff * (-1))])
error('TNS, l[79]: Inverse filter not stable!');
else
TNScoeffs = quantizedLinPredCoeff;
frameFout = filter([1 (quantizedLinPredCoeff * (-1))], 1, frameFin);
end
else
% Initializes output vectors
TNScoeffs(LPF_ORDER * 8) = 0;
frameFout(1024) = 0;
bandEnergy(SHORT_WINDOW_NUMBER_OF_BANDS) = 0;
for subFrameIndex = 1:8
subFrame = frameFin((subFrameIndex - 1) * 128 + 1:subFrameIndex * 128);
% Calculates the energy per band
for band = 1:SHORT_WINDOW_NUMBER_OF_BANDS - 1
bandEnergy(band) = sumsqr(subFrame(TNSTables.B219b(band, 2) + 1:TNSTables.B219b(band + 1, 2)));
end
bandEnergy(SHORT_WINDOW_NUMBER_OF_BANDS) = sumsqr( ...
subFrame(TNSTables.B219b(SHORT_WINDOW_NUMBER_OF_BANDS, 2) + 1:...
TNSTables.B219b(SHORT_WINDOW_NUMBER_OF_BANDS, 3) + 1));
% Calculates the normalization factors
normalizationFactor(128) = 0;
for normIndex = 1:128
bandIndices = find(TNSTables.B219b(:, 2) >= normIndex - 1, 1);
if ~isempty(bandIndices)
normalizationFactor(normIndex) = sqrt(bandEnergy(bandIndices));
else
normalizationFactor(normIndex) = sqrt(bandEnergy(find(TNSTables.B219b(:, 3) <= normIndex - 1, 1)));
end
end
% Smooths normalization factors
for normIndex = 127:-1:1
normalizationFactor(normIndex) = (normalizationFactor(normIndex) + normalizationFactor(normIndex + 1)) / 2;
end
for normIndex = 2:128
normalizationFactor(normIndex) = (normalizationFactor(normIndex) + normalizationFactor(normIndex - 1)) / 2;
end
% Normalizes MDCT coefficients according to each band energy
normalizedFrameFin = subFrame ./ normalizationFactor';
% Calculates the linear prediction coefficients
[linPredCoeff, ~] = lpc(normalizedFrameFin, LPF_ORDER);
% Quantizes these coefficients
quantizedLinPredCoeff(LPF_ORDER) = 0;
for coeffIndex = 1:length(linPredCoeff)
quantizedLinPredCoeff(coeffIndex - 1) = asin(linPredCoeff(coeffIndex));
if linPredCoeff(coeffIndex) >= 0
quantizedLinPredCoeff(coeffIndex - 1) = round(quantizedLinPredCoeff(coeffIndex - 1) * ...
(bitshift(1, COEF_RES - 1) - 0.5) / (pi / 2));
quantizedLinPredCoeff(coeffIndex - 1) = quantizedLinPredCoeff(coeffIndex - 1) / ...
(bitshift(1, COEF_RES - 1) - 0.5) / (pi / 2);
quantizedLinPredCoeff(coeffIndex - 1) = sin (quantizedLinPredCoeff(coeffIndex - 1));
else
quantizedLinPredCoeff(coeffIndex - 1) = round(quantizedLinPredCoeff(coeffIndex - 1) * ...
(bitshift(1, COEF_RES - 1) + 0.5) / (pi / 2));
quantizedLinPredCoeff(coeffIndex - 1) = quantizedLinPredCoeff(coeffIndex - 1) / ...
(bitshift(1, COEF_RES - 1) + 0.5) / (pi / 2);
quantizedLinPredCoeff(coeffIndex - 1) = sin (quantizedLinPredCoeff(coeffIndex - 1));
end
end
% Filters MDCT coefficients
if ~isstable(1, [1 (quantizedLinPredCoeff * (-1))])
error('TNS, l[79]: Inverse filter not stable!');
else
TNScoeffs((subFrameIndex - 1) * 4 + 1:subFrameIndex * 4) = quantizedLinPredCoeff;
frameFout((subFrameIndex - 1) * 128 + 1:subFrameIndex * 128) = ...
filter([1 (quantizedLinPredCoeff * (-1))], 1, subFrame);
end
end
end
end