function [t,x]=idft(X,fs,varargin)
% idft Inverse discrete Fourier transform.
% [t,x]=idft(X,fs) is the inverse discrete Fourier transform of
% frequency component X sampled at frequency sampling fs. The output
% consists of vector t which has the time index (x axis) and vector x
% which contains the values of x(t) (y axis). The length of the
% vector x is equal to the number of frequency components in K.
%
% [t,x]=idft(X,fs,N) computes the iDFT of frequency components X
% sampled at frequency fs and outputs a vector x of length N which
% contains the samples of x(t) sampled at sampling frequency fs and
% of duration T=N/fs.
%
% [t,x]=idft(X,fs,'centered') computes the iDFT of frequency
% components X where it is assumed that these components have been
% centered around k=0 and which contains the X(k) for k=0 (see output
% X_c of dft function; help dft).
%
% [t,x]=idft(X,fs,N,'centered') computes the iDFT of frequency
% components X where it is assumed they are centered around k=0 (see
% above) and outputs a vector x with N samples of x(t).
%
% See also ifft, fft, dft.
% Created by Fernando Gama (fgama@seas.upenn.edu) for ESE-224 course. Spring
% 2016.
%%\\\\\ START: SANITY CHECK OF INPUTS.
% Check that the inputs are correct
if ~isnumeric(fs) % Check if fs is a number.
error_msg='The sampling frequency should be a positive number.';
error(error_msg);
end
if ~isnumeric(X) % Check if x is a number.
error_msg='The input signal must be a vector';
error(error_msg);
end
if sum(ismember(size(X),1))~=1 % Check if it is actually a vector
% (and not a matrix).
error_msg='The input signal must be a vector';
error(error_msg);
end
X=reshape(X,length(X),1); % Turn X into a column vector.
% First of all, we need to compute the length N of the signal x:
K=length(X);
% Check if an input K was used:
if ~isempty(varargin) % If the third argument is there
if length(varargin)>2
error_msg='Too many input arguments.';
error(error_msg);
end
if length(varargin)==2
N=varargin{1}; % Assign it to K because it is supposed to be that
% parameter that is set on the third argument.
situation=varargin{2}; % Saves if it has to be centered or not.
end
if length(varargin)==1
aux=varargin{1};
if ischar(aux)
situation=aux;
N=K;
elseif isnumeric(aux)
N=aux;
situation=[];
else
N='error';
end
end
if ~isnumeric(N) % If the input is not a number, we get an error.
error_msg=['Third argument should be a positive ' ...
'integer corresponding to the number of DFT' ...
' coefficients or the legend centered. See' ...
' help idft.'];
error(error_msg);
end
if N<=0
error_msg=['The number of frequencies of the DFT has to be'...
' a positive number'];
error(error_msg);
end
if ~isempty(situation)
if ~strcmp(situation,'centered')
error_msg=['Unidentified request for computing iDFT.'...
' See help idft'];
error(error_msg);
end
end
else
N=K; % If no specific number of frequencies was selected, use the same
% as the length of the signal.
situation=[];
end
% Frequency cannot be zero
if ~fs
error('Frequency cannot be zero.');
end
% If the sampling frequency is a negative number, just use the positive.
if fs<0
warning_msg='Absolute value of sampling frequency is used instead';
warning(warning_msg);
fs=-fs;
end
%%\\\\\ END: SANITY CHECK OF INPUTS.
%%\\\\\ START: COMPUTATION OF DFT.
% Several methods are used to output such DFT. Only the most efficient one is
% left uncommented. But the rest of them are included for educative purposes.
% The computation of times is rather straightforward. If we know that we
% took samples every Ts=1/fs seconds, and we know we have N samples, then,
% the duration of the signal is T=N*Ts=N/fs. Then, we need to fit, starting
% from t=0, N samples, one every time Ts. Then,
T=N/fs;
t=(0:1/fs:T-1/fs)';
% \\\\\ CENTERED FFT.
% If the DFT was centered, then just uncenter it before doing all the idft
% processing.
if strcmp(situation,'centered')
X=circshift(X,-(ceil(K/2)-1));
end
% \\\\\ METHOD 1: For loops
% The for loops methos is pretty analogous to the one adopted in Method 1
% of dft() function. Try to adapt that one to see if you understood how the
% for loops method works. For that, you'll need to recall the iDFT
% definition (eq. 1, lab 3).
% x(n) = 1/sqrt(K) sum_{k=0 to K-1} X(k) exp(j * 2pi * k * n / N);
% \\\\ METHOD 2: Matrix form
% Using for loops in matlab is rather expensive. Matlab is already optimized to
% work with vectors and matrices, so it's a good idea to take advantage of this,
% together with the built-in elementwise operators.
% Following the mathematical development from Method 2 as explained in the dft.m
% file, adapt it to perform the matrix computation of the IDFT. Analyze if K and
% N should be treated any differently. Is there any relationship between the DFT
% matrix WKN and the iDFT matrix?
% \\\\\ METHOD 3: Built-in fft() function
% Even though the matrix form is fast, it is still not fast enough for large
% signals x. For that, it is better to use the built in fft() function which is
% the optimal way to compute a dft. Besides, it is really easy to code:
x=ifft(X,N)*sqrt(N);
%%\\\\\ END: COMPUTATION OF DFT.
end