function signal = robot(x, R, Fs, winLen, hopFactor)
% x - input signal audio
% R - scale factor of the time axis
% Fs - Sample Rate of the incoming signal
% winLen - the length of the Hanning Window and the FFT size 
% hopFactor - factor by which the Hanning Window moves. hopFactor +
% [Window Overlap] = 1
% This function creates a simulated 'robot' voice that attempts to create
% synthesized speech effect.  So that the input sounds as if it was 
% generated from a computer.
% written by John Arroyo, ja2124@columbia.edu

if nargin < 4
    winLen = 256; % a window length of 256 gives a nice synthesized speech sound
    hopFactor = 1/4; %1/4 for best reconstruction
elseif nargin < 5
    hopFactor = 1/4; %1/4 for best reconstruction
end

% a 75% window overlap needed for a smooth reconstruction.
% the integer is equal to 1-x%=hopFactor, 50% - 75% overlap is optimal which
% gives the vocoder the ability to handle fractional time scaling shifts 
% (fractions of the hamming window)
hopSize = winLen*hopFactor;

% invert R since the pitch is inversely proportional to the time scale
% factor needed.  
R = 1/R;

% encode the signal using stft (using a hann window)
X = encode(x, winLen, hopSize);

% Calculate the new time axis
sizeX = size(X,2)-2;
time = 0:R:sizeX; %step by the time scale, R

% Interpolate as is done with time shifting and create the robot effect
% Xint = interpolate(X, time, hopSize);
Xrows = size(X,1);
N = 2*(Xrows-1);

% Calculate the expected phase advance
expPhaseAdv = zeros(N/2+1,1);
expPhaseAdv(2:(1 + N/2),1) = (2*pi*hopSize)./(N./(1:(N/2))');

% Phase accumulator, set the initial phase accumulation to the values in
% the first windowed bin of the encoded signal
phaseX = angle(X(:,1));

winIndex = 1; %begin the window index with 1

for i = time
    % Get the 2 columns of X to interpolate from
    X1 = X(:,floor(i)+1);
    X2 = X(:,floor(i)+2);
    
    % find the interpolated magnitude from the two columns
    % e.g.: to interpolate 2 points into 4, X(3) = (1/3)X1 + (2/3)X2
    scale = i - floor(i); % finds the scaling factor of each of the 2 columns being interpolated, 0 >= scale < 1
    Xmag = (1-scale)*abs(X1) + scale*(abs(X2)); % scale1*X1 + scale2*X2 
       
    % Generate the the current column of Xint (the interpolated Hann
    % Window)
    Xint(:,winIndex) = Xmag .* exp(j*phaseX); %x = mag*e^jw
    winIndex = winIndex+1;
    
    % Generate Phase Accumulator
    phaseX = phaseX + expPhaseAdv; 
    % removing the expected phase advance above generate a nice robotic
    % sound, less dynamic, yet very cool.  removing that term would keep
    % the phase consant for all X
end

% turn back into a waveform, inverse window and fft
signal = decode(Xint, winLen, hopSize)';