2
votes

I'm trying to obtain the power in a certain band, but I want to do this in the time domain and not in the frequency domain. The problem - the bands are very tight and therefore using simple filters create overlapping "tails".

Let [a1 a2]Hz is the band I would like to calculate the power for. I can imagine I'm multiplying the frequency domain by a rectangle signal, and therefore I can get it's ifft in time so I may do a convolution in time.

The code is: (matlab) for x - the signal in time, X=fft(x), W - the window in frequency, w=ifft(W)

filteredX=X.*W;
Fx=ifft(filteredX);
Fx2=conv(x,w,'same');

The results of the signals are different. While the filteredX shows the correct spectrum, the fft of Fx2 (the results of the convolution) is completely different.

Any suggestions?

EDIT:

As suggested by EitanT (thanks), I've played around with the following code:

im = fix(255 * rand(500,1)); 
mask = ones(4,1) / 16; 

% # Circular convolution
resConv = conv(im, mask);

% # Discrete Fourier transform
M = size(im, 1) + size(mask, 1);
resIFFT = ifft(fft(im, M) .* fft(mask, M));
% # Not needed any more - resIFFT = resIFFT(1:end-1);  % # Adjust dimensions

% # Check the difference
max(abs(resConv(:) - resIFFT(:)))

Which works fine, but I can't use it so I had to change the parts that are concerned with size issues and got the following (please see comments):

 im = fix(255 * rand(500,1)); 
mask = ones(4,1) / 16; 

% # Circular convolution
resConv = conv(im, mask,'same'); % # instead of conv(im, mask)

% # Discrete Fourier transform
M = size(im, 1) % # Instead of: M = size(im, 1) + size(mask, 1);
resIFFT = ifft(fft(im, M) .* fft(mask, M));
resIFFT = resIFFT(1:end-1);  % # Adjust dimensions

% # Check the difference
max(abs(resConv(:) - resIFFT(:)))

If though I would expect to get the same results, now the difference is much higher.

2
possible duplicate of Verify the convolution theorem. Just use fft and conv instead of fft2 and conv2, respectively.Eitan T
Thank you Eitan. After playing a bit with the referenced code it seems that the problem is with size. I've got a 1XN frequency rectangle (W) and a 1XN frequency spectrum (X). The ifft of w and the signal x are N points long each and the convolution in (N+N+1) long. Taking the options 'same' in the convolution does extracts the needed N points, but the result in frequency is not identical to the multiplication. Not even closeBioSP
By default, the conv function filters in the forward direction, so the "extra" time points are being added to the end of the original samples. See my answer below for a more detailed breakdown.cjh

2 Answers

2
votes

Eitan's earlier verification of the convolution theorem is excellent. Here, I wanted to demonstrate time-domain convolution for filtering a particular frequency band, and show it is equivalent to frequency-domain multiplication.

Beyond knowing how to run the fft and ifft function, there are two pieces required in making this work:

  1. determining the frequency (Hz) of each Fourier component returned by the fft function
  2. padding the signal before fft, and cropping it after ifft or after conv function.

The code below generates a random signal, performs both time-domain and freq-domain filtering, and shows the equivalence in a figure something like this:

enter image description here

Nsamp = 50;  %number of samples from signal X
X = randn(Nsamp,1);  %random Gaussian signal
fs = 1000;     %sampling frequency

NFFT = 2*Nsamp;  %number of samples to be used in fft (this will lead to padding)

bandlow = 250;  %lower end of filter band (just an example range)
bandhigh = 450; %upper end of filter band

%construct a frequency axis so we know where Fourier components are

if mod(NFFT,2) == 0 %if there is an even number of points in the FFT
    iNyq = NFFT/2;     %index to the highest frequency
    posfqs = fs*(0:iNyq)/NFFT;  %positive frequencies
    negfqs = -posfqs(end-1:-1:2);  %negative frequencies

else  %if there is an odd number of point in the FFT
    iNyq = floor(NFFT/2);     %index to the highest frequency
    posfqs = fs*(0:iNyq)/NFFT;  %positive frequencies
    negfqs = -posfqs(end:-1:2);  %negative frequencies
end

fqs = [posfqs'; negfqs'];   %concatenate the positive and negative freqs

fftX = fft(X,NFFT);  % compute the NFFT-point discrete Fourier transform of X
                     % becuse NFFT > Nsamp, X is zero-padded

% construct frequency-space mask for the desired frequency range
W = ones(size(fftX)) .* ( and ( abs(fqs) >=  bandlow, abs(fqs) < bandhigh) );

fftX_filtered = fftX.*W; %multiplication in frequency space
X_mult_filtered = ifft( fftX_filtered, NFFT);  %convert the multiplicatively-filtered signal to time domain

w = ifft(W,NFFT); %convert the filter to the time domain
X_conv_filtered = conv(X, w); %convolve with filter in time domain

%now plot and compare the frequency and time domain results
figure; set(gcf, 'Units', 'normalized', 'Position', [0.45 0.15 0.4 0.7])

subplot(3,1,1); 
plot(X)
xlabel('Time Samples'); ylabel('Values of X'); title('Original Signal')

subplot(3,1,2); 
plot(X_conv_filtered(1:Nsamp))
xlabel('Time Samples'); ylabel('Values of Filtered X'); title('Filtered by Convolution in Time Domain')

subplot(3,1,3); 
plot(X_mult_filtered(1:Nsamp))
xlabel('Time Samples'); ylabel('Values of Filtered X'); title('Filtered by Multiplication in Frequency Domain')

for sp = 1:3; subplot(3,1,sp); axis([0 Nsamp -3 3]); end
-1
votes

Here's an excellent example: https://www.youtube.com/watch?v=iUafo2UZowE

EDIT:

Just don't forget the padding. for 1d signals it's like this:

lh=length(h);
lx=length(x);

h=[h zeros(1,lx-1)];
x=[x zeros(1,lh-1)];

The rest is simple:

H=fft(h);
X=fft(x);

Y=H.*X;

y=ifft(Y);

stem(y)

If you want to plot the response vs. time:

let's say nh and nx is corresponding times of h and x samples, then the corresponding times of the response samples can be calculated like this:

n=min(nh)+min(nx):+max(nh)+max(nx);

And finally

stem(n,y)