|
|
|
function x = iAACoder3(AACSeq3, fNameOut)
|
|
|
|
%Implementation of AAC decoder
|
|
|
|
% Usage x = iAACoder3(AACSeq3, fNameOut), where:
|
|
|
|
% Inputs
|
|
|
|
% - fNameOut is the filename and path of the file that will be
|
|
|
|
% written after decoding
|
|
|
|
% - AACSeq3 is an array of structs containing K structs, where K is
|
|
|
|
% the number of computed frames. Every struct of the array consists
|
|
|
|
% of:
|
|
|
|
% * a frameType,
|
|
|
|
% * a winType,
|
|
|
|
% * chl.TNScoeffs which are the quantized TNS coefficients of
|
|
|
|
% this frame's left channel,
|
|
|
|
% * chr.TNScoeffs which are the quantized TNS coefficients of
|
|
|
|
% this frame's right channel,
|
|
|
|
% * chl.T which are the psychoacoustic thresholds of this frame's
|
|
|
|
% left channel,
|
|
|
|
% * chr.T which are the psychoacoustic thresholds of this frame's
|
|
|
|
% right channel,
|
|
|
|
% * chl.G which are the quantized global gains of this frame's
|
|
|
|
% left channel,
|
|
|
|
% * chr.G which are the quantized global gains of this frame's
|
|
|
|
% right channel,
|
|
|
|
% * chl.sfc which is the Huffman encoded sfc sequence of this
|
|
|
|
% frame's left channel,
|
|
|
|
% * chr.sfc which is the Huffman encoded sfc sequence of this
|
|
|
|
% frame's right channel,
|
|
|
|
% * chl.stream which is the Huffman encoded quantized MDCT
|
|
|
|
% sequence of this frame's left channel,
|
|
|
|
% * chr.stream which is the Huffman encoded quantized MDCT
|
|
|
|
% sequence of this frame's right channel,
|
|
|
|
% * chl.codebook which is the Huffman codebook used for this
|
|
|
|
% frame's left channel
|
|
|
|
% * chr.codebook which is the Huffman codebook used for this
|
|
|
|
% frame's right channel
|
|
|
|
%
|
|
|
|
% Output
|
|
|
|
% - x is an array containing the decoded audio samples
|
|
|
|
|
|
|
|
% Initializes an array to hold the decoded samples
|
|
|
|
decodedAudio(1024 * (length(AACSeq3) + 1), 2) = 0;
|
|
|
|
% Initializes an array to hold both audio channels
|
|
|
|
frameF(1024, 2) = 0;
|
|
|
|
|
|
|
|
% Decodes audio file
|
|
|
|
huffLUT = loadLUT();
|
|
|
|
for i = 0:length(AACSeq3) - 1
|
|
|
|
currFrameStart = i * 1024 + 1;
|
|
|
|
currFrameStop = currFrameStart + 2047;
|
|
|
|
|
|
|
|
SL = decodeHuff(AACSeq3(i + 1).chl.stream, ...
|
|
|
|
AACSeq3(i + 1).chl.codebook, huffLUT);
|
|
|
|
SR = decodeHuff(AACSeq3(i + 1).chr.stream, ...
|
|
|
|
AACSeq3(i + 1).chr.codebook, huffLUT);
|
|
|
|
|
|
|
|
sfcL = decodeHuff(AACSeq3(i + 1).chl.sfc, 12, huffLUT)';
|
|
|
|
sfcR = decodeHuff(AACSeq3(i + 1).chr.sfc, 12, huffLUT)';
|
|
|
|
if strcmp(AACSeq3(i+1).frameType, 'ESH')
|
|
|
|
sfcDeHuffL(42, 8) = 0;
|
|
|
|
sfcDeHuffR(42, 8) = 0;
|
|
|
|
sfcDeHuffL(2:end, :) = reshape(sfcL, [41 8]);
|
|
|
|
sfcDeHuffR(2:end, :) = reshape(sfcR, [41 8]);
|
|
|
|
sfcDeHuffL(1, :) = AACSeq3(i+1).chl.G;
|
|
|
|
sfcDeHuffR(1, :) = AACSeq3(i+1).chr.G;
|
|
|
|
else
|
|
|
|
sfcDeHuffL = [AACSeq3(i+1).chl.G; sfcL];
|
|
|
|
sfcDeHuffR = [AACSeq3(i+1).chr.G; sfcR];
|
|
|
|
end
|
|
|
|
|
|
|
|
frameF(:, 1) = iAACquantizer(SL, sfcDeHuffL, ...
|
|
|
|
AACSeq3(i + 1).chl.G, AACSeq3(i+1).frameType);
|
|
|
|
frameF(:, 2) = iAACquantizer(SR, sfcDeHuffR, ...
|
|
|
|
AACSeq3(i + 1).chr.G, AACSeq3(i+1).frameType);
|
|
|
|
|
|
|
|
frameF(:, 1) = iTNS(frameF(:, 1), ...
|
|
|
|
AACSeq3(i+1).frameType, ...
|
|
|
|
AACSeq3(i + 1).chl.TNScoeffs);
|
|
|
|
frameF(:, 2) = iTNS(frameF(:, 2), ...
|
|
|
|
AACSeq3(i+1).frameType, ...
|
|
|
|
AACSeq3(i + 1).chr.TNScoeffs);
|
|
|
|
|
|
|
|
frameT = iFilterbank(frameF, AACSeq3(i+1).frameType, AACSeq3(i+1).winType);
|
|
|
|
|
|
|
|
|
|
|
|
decodedAudio(currFrameStart:currFrameStop, :) = decodedAudio(currFrameStart:currFrameStop, :) + frameT;
|
|
|
|
|
|
|
|
clearvars sfcDeHuffL sfcDeHuffR
|
|
|
|
end
|
|
|
|
|
|
|
|
audiowrite(fNameOut, decodedAudio, 48000);
|
|
|
|
x = decodedAudio;
|
|
|
|
end
|