function fft_ifft_classic( filePath, fileName )
%--------------------------------------------------------------------------
% FFT to IFFT Phase Vocoder
%
% adapted from
% VX_tstretch_real_pv.m   [DAFXbook, 2nd ed., chapter 7]
%
% Cooper Baker - 2014
%--------------------------------------------------------------------------

close all;

% Settings
%--------------------------------------------------------------------------
windowSize    = 1024;
overlap       = 4;
stretchFactor = 2;
window        = hann( windowSize, 'periodic' );
tag           = 'classic';

% Initializations
%--------------------------------------------------------------------------
if any( exist( 'fileName' ) ~= 1 )
    [ fileName, filePath ] = uigetfile( '*.wav', 'Audio File' );
end

[ input, sr ] = audioread( [ filePath, fileName ] );
hopSize       = windowSize / overlap;
sampleHopSize = hopSize / stretchFactor;
input         = [ zeros( windowSize, 1 ) ; input ; zeros( windowSize - mod( length( input ), sampleHopSize ), 1 ) ];
output        = zeros( windowSize + ceil( length( input ) * stretchFactor ), 1 );
omega         = 2 * pi * sampleHopSize * [ 0 : windowSize - 1 ]' / windowSize;
phaseOld      = zeros( windowSize, 1 );
phaseAccum    = zeros( windowSize, 1 );
sampleIndex   = 0;
frameIndex    = 0;
sampleMax     = length( input ) - windowSize;

% create progress bar dialog box
bar = waitbar( 0, '0%', 'Name', sprintf( '%s: processing %s...', mfilename, fileName ) );

% Processing Loop
%--------------------------------------------------------------------------
while sampleIndex < sampleMax
    % copy and window the input frame
    frame = input( sampleIndex + 1 : sampleIndex + windowSize) .* window;

    % shift zero frequency component to center of spectrum
    frame = fftshift( frame );

    % perform an fft on the input frame
    spect = fft( frame );

    % cartesian to polar conversion
    mag   = abs  ( spect );
    phase = angle( spect );

    % subtract expected phase procession and compute phase delta
    phaseWrap = phase - phaseOld - omega;
    phaseWrap = mod( phaseWrap + pi, -2 * pi ) + pi;

    % add expected phase procession
    phaseDelta = omega + phaseWrap;
    phaseOld  = phase;

    % apply stretch factor to phase and compute accumulated phase
    phaseAccum = phaseAccum + phaseDelta * stretchFactor;
    phaseAccum = mod( phaseAccum + pi, -2 * pi ) + pi;

    % polar to cartesian conversion
    spect = ( mag .* exp( 1i * phaseAccum ) );

    % perform an ifft on the spectrum
    frame = ifft( spect );

    % discard imaginary data
    frame = real( frame );

    % shift zero frequency component to center of spectrum
    frame = fftshift( frame );

    % apply the window
    frame = frame .* window;

    % normalize the frame
    frame = frame / windowSize;

    % overlap-add frame into output buffer
    output( frameIndex + 1 : frameIndex + windowSize ) = output( frameIndex + 1 : frameIndex + windowSize ) + frame;

    % increment indices
    sampleIndex = sampleIndex + sampleHopSize;
    frameIndex  = frameIndex  + hopSize;

     % update the progress bar
    progress = ( sampleIndex / sampleMax );
    waitbar( progress, bar, sprintf( '%2.3f%%', progress * 100 ) )
end

% close progress bar dialog box
close( bar );

% Output
%--------------------------------------------------------------------------

% crop output buffer
output = output( windowSize + 1 : length( output ) );

% normalize output buffer
normCoeff = 1 / max( abs( output ) );
output    = output * normCoeff;

% plot output
timevector = linspace( 0, length( output ) / sr, length( output ) );
plot( timevector, output );

% create comment string
commentString = sprintf( 'WinSize: %.0f,\nOverlap: %.0f,\nStretch: %.2f,\nWindow: %s', windowSize, overlap, stretchFactor, 'Hann' );

% write audio file to disk
[ a, fileName, b ] = fileparts( fileName );
outFile = sprintf( '%s.%s.wav', fileName, tag );
audiowrite( outFile, output, sr, 'BitsPerSample', 32, 'Artist', 'NormCoeff', 'Title', num2str( normCoeff ), 'Comment', commentString );

% EOF
