%% Perfect Reconstruction
% Perfect reconstruction is when the output of dsp.ISTFT matches the input to dsp.STFT. Perfect reconstruction is obtained if the analysis window, g\left(n\right), obeys the constant overlap-add (COLA) property at hop-size R.
% \sum_{m=-\infty }^{\infty } g\left(n-\textrm{mR}\right)=1,\;\forall n\in \;Z\;\;\;\;\;\left(g\in \textrm{COLA}\left(R\right)\right)
% A signal is perfectly reconstructed if the output of the dsp.ISTFT object matches the input to the dsp.STFT object.
%
%% iscola Function
% The iscola function checks that the specified window and overlap satisfy the COLA constraint to ensure that the inverse short-time Fourier transform (ISTFT) results in perfect reconstruction for non-modified spectra. The function returns a logical true if the combination of input parameters is COLA-compliant and a logical false if not. The method argument of the function is set to 'ola' or 'wola' depending on whether the inversion method uses weighted overlap-add (WOLA).
% Check if hann() window of length 120 samples and an overlap length of 60 samples is COLA compliant.

winLen = 120;
overlapLen = 60;
win = hann(winLen,'periodic');
tf = iscola(win,overlapLen,'ola')

%
%% Initialization
% Initialize the dsp.STFT and dsp.ISTFT System objects with this hann window that is COLA compliant. Set the FFT length to equal the window length.

frameLen = winLen-overlapLen;
stf = dsp.STFT('Window',win,'OverlapLength',overlapLen,'FFTLength',winLen);
istf = dsp.ISTFT('Window',win,'OverlapLength',overlapLen,'WeightedOverlapAdd',0);

%
%% Reconstruct Data
% Compute the STFT of a random signal. Set the length of the input signal to equal the hop length (window length – overlap length). Since the window is COLA compliant, the ISTFT of this non-modified spectra perfectly reconstructs the original time-domain signal.
% To confirm, compare the input, x to the reconstructed output, y. Due to the latency introduced by the objects, the reconstructed output is shifted in time compared to the input. Therefore, to compare, take the norm of the difference between the reconstructed output, y and the previous input, xprev. The norm is very small, indicating that the output signal is a perfectly reconstructed version of the input signal.

n = zeros(1,100);
xprev = 0;
for i = 1:100
    x = randn(frameLen,1);
    X = stf(x);
    y = istf(X);
    n(1,i) = norm(y-xprev);
    xprev = x;
end       
max(abs(n))

%
%% ISTFT with Weighted Overlap-Add (WOLA)
% In WOLA, a second window called the synthesis window, f\left(n\right), is applied after the IFFT operation and before overlap-add. The synthesis and analysis windows are typically identical and are usually obtained by taking the square root of windows satisfying COLA (thereby ensuring perfect reconstruction).
%
%% iscola Function
% Check if sqrt(hann()) window of length 120 samples and an overlap length of 60 samples is WOLA compliant. Set the method argument of the iscola function to 'wola'. The output of the iscola function is 1 indicating that this window is WOLA compliant.

winWOLA = sqrt(hann(winLen,'periodic'));
tfWOLA = iscola(winWOLA,overlapLen,'wola')

%
%% Reconstruct Data with WOLA
% Release the dsp.STFT and dsp.ISTFT System objects and set the window to sqrt(hann(winLen,'periodic')) window. To use weighted overlap-add on the ISTFT side, set the 'WeightedOverlapAdd' to true.

release(stf);
release(istf);
stf.Window = winWOLA;
istf.Window = winWOLA;
istf.WeightedOverlapAdd = true;

n = zeros(1,100);
xprev = 0;
for i = 1:100
    x = randn(frameLen,1);
    X = stf(x);
    y = istf(X);
    n(1,i) = norm(y-xprev);
    xprev = x;
end       
max(abs(n))

% The norm of the difference between the input signal and the reconstructed signal is very small indicating that the signal has been reconstructed perfectly.
%
% Copyright 2018 The MathWorks, Inc.