Inverse Fourier of a Discrete and Finite Sampling Window - matlab

I am trying to find the inverse Fourier of a discrete sampling window with N_f = 11 elements. I am expecting to see a periodic Sinc-like signal in the time-domain:
However, this is the output I get:
Why the number of observed oscillations in my output is more than the expected output?
N_f = 11; % Number of samples in the finite sampling window in Frequency domain
delta_f = 1;
f = [-N_f/2+1:delta_f:N_f/2];
wf = ones(1, N_f)/N_f; % W(f):finite sampling window in Frequency Domain
N_t =128;
wt = ifftshift(ifft(wf, N_t))*N_t; % w(t):Inverse Fourier of the window

I think one of the issues with your code is related to the location of the origin. You create an array wf with 11 ones (and normalized), then call ifft(wf,128). This pads the array with zeros to a size of 128, but the 11 ones are on the left side. You can see this by doing
fft(ifft(wf, N_t))
Thus, your window is shifted by 5 samples to the right, covering frequency bins 0 through 11, rather than -5 through 5 (or identically, 0 through 5 and 124 through 128).
The code below creates a signal with 128 samples, and fills the 11 frequency bins around the middle with 1/11. By calling ifftshift we rotate the signal such that the middle element is moved to the leftmost bin. Now bins 0 through 5 and 124 through 128 are non-zero. I then call ifft, and fftshift to move the 0 frequency back to the middle of the signal. Finally, I plot three repetitions of this signal.
N_f = 11; % Number of samples in the finite sampling window in Frequency domain
N_t = 128;
wf = zeros(1,N_t);
wf( N_t/2 - floor(N_f/2) + 1 : N_t/2 + floor(N_f/2) + 1 ) = 1 / N_f;
wt = fftshift(ifft(ifftshift(wf))) * N_t;
figure; plot(repmat(wt,1,3))
As you can see, the result is as you expected it. Note that the wt result of ifft is actually real-valued. The result of your inverse transform wasn't real-valued, you had to ignore the imaginary component to produce your plot. That's a sign that the input signal wasn't symmetric!
We can change N_f to be twice as large, yielding a result similar to yours, but with a purely real output:
N_f = 21;
N_t = 128;
wf = zeros(1,N_t);
wf( N_t/2 - floor(N_f/2) + 1 : N_t/2 + floor(N_f/2) + 1 ) = 1 / N_f;
wt = fftshift(ifft(ifftshift(wf))) * N_t;
figure; plot(repmat(wt,1,3))

Related

Generate a Rectangular Pulse in MATLAB

I need to create a rectangular pulse with width = 7 and a range (-T/2, T/2) where T 59 msec.
I wrote this code but I'm not sure if that's correct.
w = 7;
T = 59;
t = -T/2:1:T/2;
rect = rectpuls(t, w);
plot(t, rect);
This code generates a rectangular pulse but I'm not sure if it's right. Also, I'm not quite sure what the t = -T/2:1:T/2; means. I mean the range is from -29.5 to 29.5 with step 1. When I set this to 0.1 or 0.01 my pulse is better. Why does this affect my output?
Note that the second thing I have to do is to create a periodic sequence of clock pulses. I don't know if this affects the way I must implement my initial rectangular pulse.
When you increase the number of increments a numerical function (such as Matlab rectpuls) uses in its process of discretizing the continuous, you'll have as consequence that the accuracy of said function is going to improve, at the expense (in this case, negligible) of added computational cost. You are doing exactly this, when you discretize employing smaller time-steps, from 1 to 0.1 to 0.01.
To create a periodic sequence of identical rectangular pulses, you can call the function in a loop:
w = 7;
T = 59;
t = -T/2:1:T/2;
t_size = size(t);
N = 10;
rect = zeros(N, t_size(2));
interval = 20;
figure
plot(t, rectpuls(t, w));
xlim([-20 (N + 1)*interval]);
ylim([0 1.1]);
hold on
for i = 1:N
t = (-T/2 + i*interval): 1 :(T/2 + i*interval);
rect(i,:) = rectpuls(t - i * interval, w);
plot(t, rect(i,:));
hold on
end
The above should generate identical rectangular pulses every interval = 20 ms, over a time length of interval * (N + 1) = 220 ms.

How to add x % noise in a signal in MATLAB?

I am trying to add 5 % noise to a measured signal as follows (in MATLAB), but when I calculate percent of noise after addition, it is beyond +/- 5 % . Can you please tell me why this is the case ? Shouldnt it be within a +/- 5 % bound ?
noiseSigma = 0.05 * signal; % signal is my original signal
noise = noiseSigma .* randn(1, length(signal));
noisySignal = signal + noise;
percent_noise = 100*(noisySignal-signal)./signal;
randn draws from a normal distribution so it can be larger than 1.
If you want to limit your noise to 5 percent you can try the following:
noise_limit = 0.05 * signal;
addative_noise = noise_limit .* (2*rand(1, length(signal))-1);
result = signal+addative_noise;
This works because rand chooses values between zero and one. multiply it by two and subtract one, and it chooses values between -1 and 1.

Resampling of time signal in MATLAB

I want to resample my signal with to new time. Currently the sampling time of my signal is 0.01s, and the size of my signal and time array is 1*90001.
I am trying to use resample(x,p,q) in MATLAB, but I am a little bit confused.
Can somebody suggest the right way to use this function and how to resample my data to rate of 0.02s instead of 0.01s?
Code - this is how I am trying to use resample, with example data.
t = [0:0.03:1];
x = sin(4*pi*t);
y = resample(x, 1, 2);
ty = resample(t,1,2);
figure (1);
stem(ty, y, 'r*');
hold on;
stem(t,x,'b')
hold off
Updated Code :
t = [0 2 3 7 8 9 10 11 12 17 18 19 20 24 25 26 27 28 29 31 32 33 35 37 41 ];
A = [0 0 1 2 3 5.2 0 -1.4 0 2 2.7 2 2.3 6 7.3 0 0 -8.6 0 1 1 2.5 3 4.8 2];
plot(t,A)
% Tx = min(diff(t));
Tx = 1:0.1:25;
B = interp1(t,A,Tx); %re-make example data to have decimal points on the x-axis
y = resample(B, 2, 1);
T = 0.05;
Ty = T / (2 / 1);
ty = (0:length(y)-1)*Ty;
% A = interp1(t,ref,t2);
% A = ref;
figure
plot(Tx,B,'b')
hold on
plot(ty,y,'r')
plot(t,A,'g')
hold off
First of all you do not need to resample time line.
It is much easier to define time sampling interval variable or sampling frequency variable: T = 0.03; Fs = 1/T;
So, x resampling you perform right way: y = resample(x, 1, 2); .
But the new time line must be reconstructed via adjusted sampling interval: Ty = T / (1 / 2); ty = (0:length(y)-1)*Ty;
The resample function is suitable only for uniformly time distributed data points. If your original points are non-uniformly distributed, you need:
Interpolate your x signal to the uniform time line with the smallest sampling interval from the original time line: Tx = min(diff(t)); . See for example interp1 function.
Resample your interpolated uniformly time distributed (sampled) signal to the new sampling interval ( resample function).
your original signal is sampled with uniform sampling interval of 10 ms and you want to decrease sampling down to 20 ms. Why don't you just take every second datapoint of your original signal?
y = x(1:2:end);
ty = t(1:2:end);
UPDATE
for non regularly spaced datasets it is possible to use function resample as it is shown here: https://au.mathworks.com/help/signal/ref/resample.html#bungoxs
you can try
fs = 1/0.02;
[y, ty] = resample(x, t, fs, 1, 2)
There is another way to resample in a lower frequency your data.
Use this code:
fs=1/(timesignal(2)-timesignal(1)); %for example 48000Hz
fs_resampled=100; % [Hz] example goal value
t_original = [0:1/fs:(1/fs*(length(signal)-1))];%current time signal
t_resampled = [0:1/fs_resampled:max(t_original)];%new time signal
Signal_resampled = interp1(t_original,signal,t_resampled,'spline');
I hope that's what you wanted.
Greetings

Matlab-frequency bin of the positive and negative frequency

I am using MATLAB tutorial Frequency-Domain Linear Regression. There is one part of code, where is necessary to determine "frequency bin of the positive and negative frequency", for fft and ifft, this part of code:
freqbin = 72/12;
freqbins = [freqbin 72-freqbin]+1;
tsfit = zeros(72,1);
tsfit(freqbins) = tsdft(freqbins);
tsfit = ifft(tsfit);
mu = mean(ts);
tsfit = mu+tsfit;
Length of time series is 72, and there is 12 months is one cycle. How there can be only one frequency bin for positive frequency, how do we know that is exactly 72/12+1 (+1 is because first bin is for zero frequency), is that some formula or what?
Let's start with some general notes. If the sample rate is Fs, and the number of samples in the FFT is N, then the frequency of the bin with MATLAB index k is:
f_k = (k-1) * Fs / N ;
Or, conversely,
k = f_k * N / Fs + 1;
Hence, the elements of the FFT vector correspond to frequencies 0, Fs/N, 2*Fs/N, ..., (N-1)*Fs/N.
Note that the frequencies are invariant to shifts by Fs. In other words, f and f+Fs and f-Fs are all equivalent. So, you could consider the first half of the FFT vector to correspond to positive frequencies (index: 1 to N/2; frequency: 0 to (N/2-1)/N*Fs), and the second half to correspond to negative frequencies (index: N/2+1 to N; frequency: -Fs/2 to -Fs/N). Here I include 0 in the set of positive frequencies for brevity.
Now, coming to your specific example:
N = 72
Fs = 12 ; % samples per year
So, the positive frequency range is from 0 to Fs/2 = 6 cycles per year, corresponding to indices 1 to 36, respectively.
You are interested in finding the FFT sample corresponding to the frequency 1 cycle per year. That corresponds to index 1 * 72 / 12 + 1 = 7.
Since the FFT is symmetric for real signals, you are also interested in finding the FFT sample corresponding to the frequency -1 cycle per year, which, using the shift-invariance property, is also equivalent to -1 + Fs = 11 cycles per year. The corresponding index is (12-1) * 72 / 12 + 1 = 67.
In summary,
There are 36 positive frequencies (including 0), not 1.
The algorithm is interested in only one positive frequency with the highest magnitude.
That frequency happens to be 1 cycle per year. The corresponding MATLAB index is 7.
The mirror image of the frequency is -1 cycle per year, which corresponds to MATLAB index 67.

Why does spectrogram's result matrix not have the length of the chosen window?

I am learning about audio processing techniques and have been using a spectrogram to do analysis. Now, I would have thought that the result of the spectrogram would be an M x N matrix, where M would be the window length, and N the number of windows. However the spectrogram function returns a matrix of a different length than I would expect:
data = [...]; % the data, a 1 x 9171 array
wdw = 160; % window size
overlap = 80; % window overlap
numWindows = floor(length(data)/(wdw - overlap)) - 1; % returns 113 as expected
nfft = 256; % fft size
Fs = 16000; % sample freq
s = spectrogram(data,hamming(wdw),overlap,nfft,Fs);
s returns as a 129 x 113 matrix, whereas I would expect a 160 x 113 matrix. Does anyone know why the function truncates the length of each window?
I don't think S returns what you think it returns. From the documentation:
Each column of S contains an estimate of the short-term, time-localized
frequency content of the signal X. Time increases across the columns
of S, from left to right. Frequency increases down the rows, starting
at 0. If X is a length NX complex signal, S is a complex matrix with
NFFT rows and k = fix((NX-NOVERLAP)/(length(WINDOW)-NOVERLAP)) columns.
For real X, S has (NFFT/2+1) rows if NFFT is even, and (NFFT+1)/2 rows
if NFFT is odd.
129 is 256/2+1, which is what you get.