From dbd83c163f27da3049f6395ceeb667e90f32fd67 Mon Sep 17 00:00:00 2001 From: Apostolof Date: Sat, 26 Jan 2019 03:04:18 +0200 Subject: [PATCH] Apply fixes to level 2 --- Level_2/AACoder2.m | 17 +++++-- Level_2/SSC.m | 25 ++++------ Level_2/demoAAC2.m | 39 ++++++++++++---- Level_2/filterbank.m | 103 ++++++++++++++++++++---------------------- Level_2/iAACoder2.m | 4 +- Level_2/iFilterbank.m | 102 ++++++++++++++++++++--------------------- 6 files changed, 152 insertions(+), 138 deletions(-) diff --git a/Level_2/AACoder2.m b/Level_2/AACoder2.m index 78c9a68..78be5bf 100644 --- a/Level_2/AACoder2.m +++ b/Level_2/AACoder2.m @@ -1,5 +1,5 @@ function AACSeq2 = AACoder2(fNameIn) -%Implementation of WHAT?? //TODO!! +%Implementation of AAC encoder % Usage AACSeq2 = AACoder2(fNameIn), where: % Inputs % - fNameIn is the filename and path of the file to encode @@ -14,6 +14,9 @@ function AACSeq2 = AACoder2(fNameIn) % channel, chr.frameF which are the MDCT coefficients of this frame's % right channel + % Declares constant window type + WINDOW_TYPE = 'KBD'; + % Reads the audio file [originalAudioData, ~] = audioread(fNameIn); @@ -24,9 +27,13 @@ function AACSeq2 = AACoder2(fNameIn) nextFrameStart = (i + 1) * 1024 + 1; nextFrameStop = nextFrameStart + 2047; frameTypes{i+1} = SSC(1, originalAudioData(nextFrameStart:nextFrameStop, :), frameTypes{i}); + +% if strcmp(frameTypes{i+1}, 'ESH') +% i +% end end - % Assignes a type to the last frame + % Assigns a type to the last frame if strcmp(frameTypes{length(frameTypes) - 1}, 'LSS') frameTypes{length(frameTypes)} = 'ESH'; elseif strcmp(frameTypes{length(frameTypes) - 1}, 'ESH') @@ -40,19 +47,19 @@ function AACSeq2 = AACoder2(fNameIn) for i = 0:length(frameTypes) - 1 currFrameStart = i * 1024 + 1; currFrameStop = currFrameStart + 2047; - frameF = filterbank(originalAudioData(currFrameStart:currFrameStop, :), frameTypes{i+1}, 'KBD'); + frameF = filterbank(originalAudioData(currFrameStart:currFrameStop, :), frameTypes{i+1}, WINDOW_TYPE); [frameF(:, 1), TNScoeffsL] = TNS(frameF(:, 1), frameTypes{i+1}); [frameF(:, 2), TNScoeffsR] = TNS(frameF(:, 2), frameTypes{i+1}); AACSeq2(i + 1).frameType = frameTypes(i + 1); - AACSeq2(i + 1).winType = 'KBD'; + AACSeq2(i + 1).winType = WINDOW_TYPE; AACSeq2(i + 1).chl.TNScoeffs = TNScoeffsL; AACSeq2(i + 1).chr.TNScoeffs = TNScoeffsR; AACSeq2(i + 1).chl.frameF = frameF(:, 1); AACSeq2(i + 1).chr.frameF = frameF(:, 2); end - if true + if false [idx,label] = grp2idx(sort(frameTypes)); hist(idx,unique(idx)); set(gca,'xTickLabel',label) diff --git a/Level_2/SSC.m b/Level_2/SSC.m index 143ffd4..50ebec7 100644 --- a/Level_2/SSC.m +++ b/Level_2/SSC.m @@ -29,10 +29,8 @@ function frameType = SSC(~, nextFrameT, prevFrameType) % Determines the type of the next frame % Filters frame - nextFrameT = filter([0.7548, -0.7548], [1, -0.5095], nextFrameT, [], 1); - + nextFrameT = filter([0.7548 -0.7548], [1 -0.5095], nextFrameT, [], 1); channelFrameType = {'nan', 'nan'}; - for channel = 1:2 % Calculates sub-frame energy estimation [subFrames, ~] = buffer(nextFrameT(449:end - 448, channel), 256, 128, 'nodelay'); @@ -40,18 +38,12 @@ function frameType = SSC(~, nextFrameT, prevFrameType) % Calculates the ratio of the sub-frame energy to the average energy of % the previous sub-frames - nextIsESH = false; - for subFrameIndex = 2:8 - energyRatio = energyEstimations(subFrameIndex) / ... - mean(energyEstimations(1:subFrameIndex - 1)); - - if (energyEstimations(subFrameIndex) > 10^(-3)) && (energyRatio > 10) - nextIsESH = true; - break; - end - end - - if nextIsESH == true + energyRatios = movmean(energyEstimations, [8 0]); + energyRatios = energyEstimations ./ [energyEstimations(1) energyRatios(1:end-1)]; + + if ~isempty(find(energyEstimations > 10^(-3), 1)) && ... + ~isempty(find(energyRatios(energyEstimations > 10^(-3)) > 10, 1)) + % Next frame is ESH if strcmp(prevFrameType, 'ESH') % This frame of this channel is an EIGHT_SHORT_SEQUENCE type % frame. This means the frames of both channels will be encoded @@ -70,8 +62,9 @@ function frameType = SSC(~, nextFrameT, prevFrameType) end end + % Joins decision for both channels if strcmp(channelFrameType{1}, 'nan') || strcmp(channelFrameType{2}, 'nan') - error('SSC, l[73]: Internal error occured!') + error('SSC, l[73]: Internal error occurred!') end if strcmp(channelFrameType{1}, 'OLS') frameType = channelFrameType{2}; diff --git a/Level_2/demoAAC2.m b/Level_2/demoAAC2.m index 73156f5..fc0c42c 100644 --- a/Level_2/demoAAC2.m +++ b/Level_2/demoAAC2.m @@ -1,5 +1,5 @@ function SNR = demoAAC2(fNameIn, fNameOut) -%Implementation of WHAT?? //TODO!! +%Function that demonstrates usage of the level 2 code % Usage SNR = demoAAC2(fNameIn, fNameOut), where: % Inputs % - fNameIn is the filename and path of the file to encode @@ -15,13 +15,34 @@ function SNR = demoAAC2(fNameIn, fNameOut) [audioData, ~] = audioread(fNameIn); - figure() - plot(audioData(1:length(decodedAudio), 1) - decodedAudio(1:end, 1)) - figure() - plot(audioData(1:length(decodedAudio), 2) - decodedAudio(1:end, 2)) +% figure() +% plot(audioData(1025:length(decodedAudio)-1024, 1) - decodedAudio(1025:end-1024, 1)) +% for frame = 1:length(AACSeq1) +% if strcmp(AACSeq1(frame).frameType, 'LSS') || strcmp(AACSeq1(frame).frameType, 'LPS') +% % Add lines +% h1 = line([(frame-1)*1024+1 (frame-1)*1024+1],[-2*10^(-15) 2*10^(-15)]); +% h2 = line([frame*1024+1 frame*1024+1],[-2*10^(-15) 2*10^(-15)]); +% % Set properties of lines +% set([h1 h2],'Color','y','LineWidth',2) +% % Add a patch +% patch([(frame-1)*1024+1 frame*1024+1 frame*1024+1 (frame-1)*1024+1],[-2*10^(-15) -2*10^(-15) 2*10^(-15) 2*10^(-15)],'y') +% elseif strcmp(AACSeq1(frame).frameType, 'ESH') +% % Add lines +% h1 = line([(frame-1)*1024+1 (frame-1)*1024+1],[-2*10^(-15) 2*10^(-15)]); +% h2 = line([frame*1024+1 frame*1024+1],[-2*10^(-15) 2*10^(-15)]); +% % Set properties of lines +% set([h1 h2],'Color','r','LineWidth',2) +% % Add a patch +% patch([(frame-1)*1024+1 frame*1024+1 frame*1024+1 (frame-1)*1024+1],[-2*10^(-15) -2*10^(-15) 2*10^(-15) 2*10^(-15)],'r') +% end +% end +% set(gca,'children',flipud(get(gca,'children'))) +% +% figure() +% plot(audioData(1025:length(decodedAudio)-1024, 2) - decodedAudio(1025:end-1024, 2)) - snr(audioData(1:length(decodedAudio), 1), audioData(1:length(decodedAudio), 1) - decodedAudio(1:end, 1)) - snr(audioData(1:length(decodedAudio), 2), audioData(1:length(decodedAudio), 2) - decodedAudio(1:end, 2)) - SNR = 10*log10((sum(audioData(1:length(decodedAudio), :)) .^ 2) ./ ... - (sum(audioData(1:length(decodedAudio), :) - decodedAudio) .^ 2)); + snr(audioData(1025:length(decodedAudio)-1024, 1), audioData(1025:length(decodedAudio)-1024, 1) - decodedAudio(1025:end-1024, 1)) + snr(audioData(1025:length(decodedAudio)-1024, 2), audioData(1025:length(decodedAudio)-1024, 2) - decodedAudio(1025:end-1024, 2)) + SNR = 10*log10((sum(audioData(1025:length(decodedAudio)-1024, :)) .^ 2) ./ ... + (sum(audioData(1025:length(decodedAudio)-1024, :) - decodedAudio(1025:end-1024, :)) .^ 2)); end diff --git a/Level_2/filterbank.m b/Level_2/filterbank.m index 98fea67..56ab914 100644 --- a/Level_2/filterbank.m +++ b/Level_2/filterbank.m @@ -20,72 +20,68 @@ function frameF = filterbank(frameT, frameType, winType) persistent kaiserWindowLong kaiserWindowShort sinWindowLong sinWindowShort; if isempty(kaiserWindowLong) || isempty(kaiserWindowShort) || ... isempty(sinWindowLong) || isempty(sinWindowShort) - kaiserLong = kaiser(1024, 6*pi); + kaiserLong = kaiser(1025, 6*pi); kaiserSumLong = sum(kaiserLong); - kaiserShort = kaiser(128, 4*pi); + kaiserShort = kaiser(129, 4*pi); kaiserSumShort = sum(kaiserShort); - for n = 1:1024 - kaiserWindowLong(n) = sqrt(sum(kaiserLong(1:n))/kaiserSumLong); - kaiserWindowLong(1024 + n) = sqrt(sum(kaiserLong(1:end-n+1))/kaiserSumLong); + kaiserWindowLong(1:1024) = movsum(kaiserLong(1:1024), [1024 0]); + kaiserWindowLong(1025:2048) = movsum(flipud(kaiserLong(1:1024)), [0 1024]); + kaiserWindowLong = sqrt(kaiserWindowLong ./ kaiserSumLong); - sinWindowLong(n) = sin(pi*(n + 0.5)/2048); - sinWindowLong(1024 + n) = sin(pi*(1024 + n + 0.5)/2048); + sinWindowLong = sin(pi * ((0:2047) + 0.5) / 2048); - end - - for n = 1:128 - kaiserWindowShort(n) = sqrt(sum(kaiserShort(1:n))/kaiserSumShort); - kaiserWindowShort(128 + n) = sqrt(sum(kaiserShort(1:end-n+1))/kaiserSumShort); + kaiserWindowShort(1:128) = movsum(kaiserShort(1:128), [128 0]); + kaiserWindowShort(129:256) = movsum(flipud(kaiserShort(1:128)), [0 128]); + kaiserWindowShort = sqrt(kaiserWindowShort ./ kaiserSumShort); - sinWindowShort(n) = sin(pi*(n + 0.5)/256); - sinWindowShort(128 + n) = sin(pi*(128 + n + 0.5)/256); - end + sinWindowShort = sin(pi * ((0:255) + 0.5) / 256); end + % Initializes output array frameF(1024, 2) = 0; % Applies appropriate window to the frame - for channel=1:2 - if strcmp(frameType, 'OLS') - if strcmp(winType, 'KBD') - frameT(:, channel) = frameT(:, channel) .* kaiserWindowLong(:); - elseif strcmp(winType, 'SIN') - frameT(:, channel) = frameT(:, channel) .* sinWindowLong(:); - else - error('filterbank, l[20]: Unsupported window type input!') - end + if strcmp(frameType, 'OLS') + if strcmp(winType, 'KBD') + frameT = bsxfun(@times, frameT, kaiserWindowLong'); + elseif strcmp(winType, 'SIN') + frameT = bsxfun(@times, frameT, sinWindowLong'); + else + error('filterbank, l[20]: Unsupported window type input!') + end - frameF(:, channel) = mdct4(frameT(:, channel)); - elseif strcmp(frameType, 'LSS') - if strcmp(winType, 'KBD') - frameT(1:1024, channel) = frameT(1:1024, channel) .* kaiserWindowLong(1:1024)'; - frameT(1473:1600, channel) = frameT(1473:1600, channel) .* kaiserWindowShort(129:end)'; - frameT(1601:end, channel) = 0; - elseif strcmp(winType, 'SIN') - frameT(1:1024, channel) = frameT(1:1024, channel) .* sinWindowLong(1:1024)'; - frameT(1473:1600, channel) = frameT(1473:1600, channel) .* sinWindowShort(129:end)'; - frameT(1601:end, channel) = 0; - else - error('filterbank, l[20]: Unsupported window type input!') - end + frameF = mdct4(frameT); + elseif strcmp(frameType, 'LSS') + if strcmp(winType, 'KBD') + frameT(1:1024, :) = bsxfun(@times, frameT(1:1024, :), kaiserWindowLong(1:1024)'); + frameT(1473:1600, :) = bsxfun(@times, frameT(1473:1600, :), kaiserWindowShort(129:end)'); + frameT(1601:end, :) = 0; + elseif strcmp(winType, 'SIN') + frameT(1:1024, :) = bsxfun(@times, frameT(1:1024, :), sinWindowLong(1:1024)'); + frameT(1473:1600, :) = bsxfun(@times, frameT(1473:1600, :), sinWindowShort(129:end)'); + frameT(1601:end, :) = 0; + else + error('filterbank, l[20]: Unsupported window type input!') + end - frameF(:, channel) = mdct4(frameT(:, channel)); - elseif strcmp(frameType, 'LPS') - if strcmp(winType, 'KBD') - frameT(1:448, channel) = 0; - frameT(449:576, channel) = frameT(449:576, channel) .* kaiserWindowShort(1:128)'; - frameT(1025:end, channel) = frameT(1025:end, channel) .* kaiserWindowLong(1025:end)'; - elseif strcmp(winType, 'SIN') - frameT(1:448, channel) = 0; - frameT(449:576, channel) = frameT(449:576, channel) .* sinWindowShort(1:128)'; - frameT(1025:end, channel) = frameT(1025:end, channel) .* sinWindowLong(1025:end)'; - else - error('filterbank, l[20]: Unsupported window type input!') - end + frameF = mdct4(frameT); + elseif strcmp(frameType, 'LPS') + if strcmp(winType, 'KBD') + frameT(1:448, :) = 0; + frameT(449:576, :) = bsxfun(@times, frameT(449:576, :), kaiserWindowShort(1:128)'); + frameT(1025:end, :) = bsxfun(@times, frameT(1025:end, :), kaiserWindowLong(1025:end)'); + elseif strcmp(winType, 'SIN') + frameT(1:448, :) = 0; + frameT(449:576, :) = bsxfun(@times, frameT(449:576, :), sinWindowShort(1:128)'); + frameT(1025:end, :) = bsxfun(@times, frameT(1025:end, :), sinWindowLong(1025:end)'); + else + error('filterbank, l[20]: Unsupported window type input!') + end - frameF(:, channel) = mdct4(frameT(:, channel)); - elseif strcmp(frameType, 'ESH') + frameF = mdct4(frameT); + elseif strcmp(frameType, 'ESH') + for channel = 1:2 % Splits the frame into sub-frames [subFrames, ~] = buffer(frameT(449:end-448, channel), 256, 128, 'nodelay'); @@ -96,7 +92,8 @@ function frameF = filterbank(frameT, frameType, winType) end for subFrameIndex = 1:8 - frameF((subFrameIndex - 1) * 128 + 1:subFrameIndex * 128, channel) = mdct4(subFrames(:, subFrameIndex)); + frameF((subFrameIndex - 1) * 128 + 1:subFrameIndex * 128, channel) = ... + mdct4(subFrames(:, subFrameIndex)); end end end diff --git a/Level_2/iAACoder2.m b/Level_2/iAACoder2.m index c5243db..8da38a9 100644 --- a/Level_2/iAACoder2.m +++ b/Level_2/iAACoder2.m @@ -1,5 +1,5 @@ function x = iAACoder2(AACSeq2, fNameOut) -%Implementation of WHAT?? //TODO!! +%Implementation of AAC decoder % Usage x = iAACoder2(AACSeq2, fNameOut), where: % Inputs % - fNameOut is the filename and path of the file that will be @@ -22,7 +22,7 @@ function x = iAACoder2(AACSeq2, fNameOut) frameF(1024, 2) = 0; % Decodes audio file - for i = 0:length(AACSeq2)-1 + for i = 0:length(AACSeq2) - 1 currFrameStart = i * 1024 + 1; currFrameStop = currFrameStart + 2047; frameF(:, 1) = AACSeq2(i+1).chl.frameF; diff --git a/Level_2/iFilterbank.m b/Level_2/iFilterbank.m index c71e8d5..683be02 100644 --- a/Level_2/iFilterbank.m +++ b/Level_2/iFilterbank.m @@ -20,72 +20,68 @@ function frameT = iFilterbank(frameF, frameType, winType) persistent kaiserWindowLong kaiserWindowShort sinWindowLong sinWindowShort; if isempty(kaiserWindowLong) || isempty(kaiserWindowShort) || ... isempty(sinWindowLong) || isempty(sinWindowShort) - kaiserLong = kaiser(1024, 6*pi); + kaiserLong = kaiser(1025, 6*pi); kaiserSumLong = sum(kaiserLong); - kaiserShort = kaiser(128, 4*pi); + kaiserShort = kaiser(129, 4*pi); kaiserSumShort = sum(kaiserShort); - for n = 1:1024 - kaiserWindowLong(n) = sqrt(sum(kaiserLong(1:n))/kaiserSumLong); - kaiserWindowLong(1024 + n) = sqrt(sum(kaiserLong(1:end-n+1))/kaiserSumLong); + kaiserWindowLong(1:1024) = movsum(kaiserLong(1:1024), [1024 0]); + kaiserWindowLong(1025:2048) = movsum(flipud(kaiserLong(1:1024)), [0 1024]); + kaiserWindowLong = sqrt(kaiserWindowLong ./ kaiserSumLong); - sinWindowLong(n) = sin(pi*(n + 0.5)/2048); - sinWindowLong(1024 + n) = sin(pi*(1024 + n + 0.5)/2048); + sinWindowLong = sin(pi * ((0:2047) + 0.5) / 2048); - end - - for n = 1:128 - kaiserWindowShort(n) = sqrt(sum(kaiserShort(1:n))/kaiserSumShort); - kaiserWindowShort(128 + n) = sqrt(sum(kaiserShort(1:end-n+1))/kaiserSumShort); + kaiserWindowShort(1:128) = movsum(kaiserShort(1:128), [128 0]); + kaiserWindowShort(129:256) = movsum(flipud(kaiserShort(1:128)), [0 128]); + kaiserWindowShort = sqrt(kaiserWindowShort ./ kaiserSumShort); - sinWindowShort(n) = sin(pi*(n + 0.5)/256); - sinWindowShort(128 + n) = sin(pi*(128 + n + 0.5)/256); - end + sinWindowShort = sin(pi * ((0:255) + 0.5) / 256); end + % Initializes output array frameT(2048, 2) = 0; % Applies appropriate window to the frame - for channel=1:2 - if strcmp(frameType, 'OLS') - frameT(:, channel) = imdct4(frameF(:, channel)); + if strcmp(frameType, 'OLS') + frameT = imdct4(frameF); - if strcmp(winType, 'KBD') - frameT(:, channel) = frameT(:, channel) .* kaiserWindowLong(:); - elseif strcmp(winType, 'SIN') - frameT(:, channel) = frameT(:, channel) .* sinWindowLong(:); - else - error('filterbank, l[20]: Unsupported window type input!') - end - elseif strcmp(frameType, 'LSS') - frameT(:, channel) = imdct4(frameF(:, channel)); + if strcmp(winType, 'KBD') + frameT = bsxfun(@times, frameT, kaiserWindowLong'); + elseif strcmp(winType, 'SIN') + frameT = bsxfun(@times, frameT, sinWindowLong'); + else + error('filterbank, l[20]: Unsupported window type input!') + end + elseif strcmp(frameType, 'LSS') + frameT = imdct4(frameF); - if strcmp(winType, 'KBD') - frameT(1:1024, channel) = frameT(1:1024, channel) .* kaiserWindowLong(1:1024)'; - frameT(1473:1600, channel) = frameT(1473:1600, channel) .* kaiserWindowShort(129:end)'; - frameT(1601:end, channel) = 0; - elseif strcmp(winType, 'SIN') - frameT(1:1024, channel) = frameT(1:1024, channel) .* sinWindowLong(1:1024)'; - frameT(1473:1600, channel) = frameT(1473:1600, channel) .* sinWindowShort(129:end)'; - frameT(1601:end, channel) = 0; - else - error('filterbank, l[20]: Unsupported window type input!') - end - elseif strcmp(frameType, 'LPS') - frameT(:, channel) = imdct4(frameF(:, channel)); + if strcmp(winType, 'KBD') + frameT(1:1024, :) = bsxfun(@times, frameT(1:1024, :), kaiserWindowLong(1:1024)'); + frameT(1473:1600, :) = bsxfun(@times, frameT(1473:1600, :), kaiserWindowShort(129:end)'); + frameT(1601:end, :) = 0; + elseif strcmp(winType, 'SIN') + frameT(1:1024, :) = bsxfun(@times, frameT(1:1024, :), sinWindowLong(1:1024)'); + frameT(1473:1600, :) = bsxfun(@times, frameT(1473:1600, :), sinWindowShort(129:end)'); + frameT(1601:end, :) = 0; + else + error('filterbank, l[20]: Unsupported window type input!') + end + elseif strcmp(frameType, 'LPS') + frameT = imdct4(frameF); - if strcmp(winType, 'KBD') - frameT(1:448, channel) = 0; - frameT(449:576, channel) = frameT(449:576, channel) .* kaiserWindowShort(1:128)'; - frameT(1025:end, channel) = frameT(1025:end, channel) .* kaiserWindowLong(1025:end)'; - elseif strcmp(winType, 'SIN') - frameT(1:448, channel) = 0; - frameT(449:576, channel) = frameT(449:576, channel) .* sinWindowShort(1:128)'; - frameT(1025:end, channel) = frameT(1025:end, channel) .* sinWindowLong(1025:end)'; - else - error('filterbank, l[20]: Unsupported window type input!') - end - elseif strcmp(frameType, 'ESH') + if strcmp(winType, 'KBD') + frameT(1:448, :) = 0; + frameT(449:576, :) = bsxfun(@times, frameT(449:576, :), kaiserWindowShort(1:128)'); + frameT(1025:end, :) = bsxfun(@times, frameT(1025:end, :), kaiserWindowLong(1025:end)'); + elseif strcmp(winType, 'SIN') + frameT(1:448, :) = 0; + frameT(449:576, :) = bsxfun(@times, frameT(449:576, :), sinWindowShort(1:128)'); + frameT(1025:end, :) = bsxfun(@times, frameT(1025:end, :), sinWindowLong(1025:end)'); + else + error('filterbank, l[20]: Unsupported window type input!') + end + elseif strcmp(frameType, 'ESH') + for channel=1:2 for subFrameIndex = 1:8 subFrame = imdct4(frameF((subFrameIndex - 1) * 128 + 1:subFrameIndex * 128, channel)); @@ -94,7 +90,7 @@ function frameT = iFilterbank(frameF, frameType, winType) elseif strcmp(winType, 'SIN') subFrame = subFrame .* sinWindowShort'; end - + frameT(448 + (subFrameIndex - 1) * 128 + 1:448 + (subFrameIndex + 1) * 128, channel) = ... frameT(448 + (subFrameIndex - 1) * 128 + 1:448 + (subFrameIndex + 1) * 128, channel) + subFrame; end