How to add windows to the original signal and plot the amplitude isoline with time and frequency as coordinates? - matlab

I have original signal data, I want use windowing method, and FFT then plot 3-D amplitude, by MATLAB.
dt = 2;
Lt = 500;
Time = 2:dt:Lt;
original = (0.4*rand([Lt/dt,1])-0.2)';
L=31;
rec = rectwin(L);
% I won't do the rest.

Related

inverse fourier transform of data does not give correct amplitude

I'm trying to calculate the inverse Fourier transform of some data using Matlab. I start with raw data in the frequency domain and want to visualise the data in the time domain. Here is my MWE:
a = 1.056;
% frequency of data (I cannot change this)
w = linspace(-100,100,1e6);
L = length(w); % no. sample points
ts = L/1000; % time sampling
Ts = ts/L; % sampling rate
Fs = 1/Ts; % sampling freq
t = (-L/2:L/2-1)*ts/L; % time
Y = sqrt(pi/a)*exp(-w.^2/(4*a)); % my data
yn = Fs*ifftshift(ifft(fftshift(Y(end:-1:1)))) % numerical soln
ya = exp(-a*t.^2); % analytic solution
figure; hold on
plot(t,yn,'.')
plot(t,ya,'-')
xlabel('time, t')
legend('numerical','analytic')
xlim([-5,5])
I have adapted the code from this question however the amplitude is too large:
Can you please tell me what I'm doing wrong?
There are three issues with your code:
You define ts = L/1000 and then compute Fs, which gives you 1000. But Fs is given by the w array you've set up: the full range of w is 2*pi*Fs:
Fs = -w(1)/pi; % sampling freq
Ts = 1/Fs; % sampling rate
Or, equivalently, set Fs = mean(diff(w))*L / (2*pi)
w is defined, but does not include 0. Just like you define t carefully to include the 0 in just the right place, so should you define w to include 0 in just the right place. One simple way to do this is to define it with one more value, then delete the last value:
w = linspace(-100,100,1e6+1);
w(end) = [];
If your input data does not include the 0 frequency, you should resample it so that it does. The DFT (FFT) expects a 0 frequency bin.
You're using ifftshift and fftshift reversed: fftshift shifts the origin from the leftmost array element to the middle, and ifftshift shifts it from the middle to the left. You define your signal with the origin in the middle, so you need to use ifftshift on it to move the origin where the fft and ifft functions expect it. Use fftshift on the output of these two functions to center the origin for display. Because your data is even sized, these two functions do exactly the same thing, and you will not notice the difference. But if the data were odd sized, you'd see the difference.
The following code gives a perfect match:
a = 1.056;
% frequency of data (I cannot change this)
w = linspace(-100,100,1e6+1); w(end) = [];
L = length(w); % no. sample points
Fs = -w(1)/pi; % sampling freq
Ts = 1/Fs; % sampling rate
t = (-L/2:L/2-1)*Ts; % time
Y = sqrt(pi/a)*exp(-w.^2/(4*a)); % my data
yn = Fs*fftshift(ifft(ifftshift(Y(end:-1:1)))); % numerical soln
ya = exp(-a*t.^2); % analytic solution
figure; hold on
plot(t,yn,'.')
plot(t,ya,'-')
xlabel('time, t')
legend('numerical','analytic')
xlim([-5,5])

Reconstruction of Digital Signal using the sinc Function

I am trying to reconstruct the signal cos(2*pi*300e6) at the sampling frequency 800e6 using the sinc function in MATLAB. When I type in the following code, I'm instead getting something very noisy--not what I am looking for. What am I doing wrong? Thank you in advance!
Code:
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1reconstructed = zeros(1,length(t)); %preallocating for speed
samples = length(ts);
for i = 1:1:length(t)
for n = 1:1:samples
x1reconstructed(i) = sum(x1resampled(n)*sinc(pi*(t(i)-n*Ts)/Ts));
end
end
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)
Two problems with the code:
You are not accumulating the reconstructed samples properly. Specifically, you are only retaining one value from the resampled signal, not all samples.
sinc in MATLAB uses the normalized sinc function. This means that you don't have to multiply the argument by pi. Recall that the reconstruction formula requires the normalized sinc function, so there is no multiplication of pi in the argument of the function.
Therefore you simply have to change the code inside the for loop:
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1reconstructed = zeros(1,length(t)); %preallocating for speed
samples = length(ts);
for i = 1:1:length(t)
for n = 1:1:samples
x1reconstructed(i) = x1reconstructed(i) + x1resampled(n)*sinc((t(i)-n*Ts)/Ts); %%% CHANGE
end
end
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)
I now get this plot:
To make things more efficient, definitely use the sum function but do it over all samples. So your for loop should now be:
for i = 1:1:length(t)
x1reconstructed(i) = sum(x1resampled .* sinc((t(i) - (1:samples)*Ts) ./ Ts));
end
You can accomplish the same thing, but more efficiently, using the discrete Fourier transform (DFT):
F1 = 300e6;
Fs = 800e6;
tmin = 0;
tmax = 10/F1;
t = tmin:1e-12:tmax;
x1 = cos(2*pi*F1*t);
Ts = 1/Fs;
ts = tmin:Ts:tmax;
x1resampled = cos(2*pi*F1*ts);
x1resampledDFT = fftshift(fft(x1resampled));
n = (length(x1)-length(x1resampledDFT))/2;
x1reconstructedDFT = [zeros(1,ceil(n)),x1resampledDFT,zeros(1,floor(n))];
x1reconstructed = ifft(ifftshift(x1reconstructedDFT));
x1reconstructed = x1reconstructed / length(x1resampled) * length(x1reconstructed);
figure(1)
subplot(2,1,1)
plot(t,x1)
hold on
stem(ts,x1resampled)
subplot(2,1,2)
plot(t,x1reconstructed)
What is happening here is that I'm padding the DFT (as computed efficiently using fft) with zeros to the desired size. The inverse transform then results in the signal interpolated using the sinc interpolator. To preserve the signal strength some normalization is needed. Any differences you see with Rayryeng's answer is due to the periodic nature of the DFT: basically the sinc functions, as they exit the signal domain on the right, come back in at the left; the data at the right end of the plot influence the result at the left end of the plot and vice versa.
To learn more about interpolation using the Fourier transform, see this blog post.

MATLAB FFT -> Equalizer -> iFFT

I’m trying to implement a 32 point FFT - Equalizer - iFFT
On a step by step basis. I input a Time domain signal to a FFT block and then used iFFT to obtain the original data back.
Naturally after FFT, I get 32 points of symmetrical real and imaginary data.
I tried,
Step 1:
fft_sig = fft(data_processing_block); %FFT of the signal
ifft_sig = ifft(fft_sig); %iFFT of the signal
The output matches the input. Works like a charm.
Step 2:
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig);
after_eq_im = imag(fft_sig);
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
This also works just fine.
Step 3:
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig).*1.0; % Multiply Real data with a constant
after_eq_im = imag(fft_sig).*1.0; % Multiply Imag data with a constant
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
This also works fine.
Step 4:
I replaced the constant (1.0) with an Equalizer table. Of size 32.
Eq_data_32 =[0.0;0.1347;0.2117;0.2956;0.4146;0.5300;0.5615;0.5195;0.4391;0.3621;0.2816;0.1977;0.1837;0.1172;0.0857;0.0577;0.0;0.0577;0.0857;0.1172;0.1837;0.1977;0.2816;0.3621;0.4391;0.5195;0.5615;0.5300;0.4146;0.2956;0.2117;0.1347];
Eq_data_32(1) and Eq_data_32(17) are zeros. Eq_data_32(2:16) is symmetrical to Eq_data_32(18:32).
re_Eq_data_32 = Eq_data_32; % Equalizer data for real values
im_Eq_data_32 = -(re_Eq_data_32); % Equalizer data for imaginary values
fft_sig = fft(data_processing_block); %FFT of the signal
after_eq_re = real(fft_sig).*re_Eq_data_32';
after_eq_im = imag(fft_sig).*im_Eq_data_32';
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(after_eq); %iFFT of the signal
Now the output is distorted and does not sound good. I think this is due to symmetry of the Equalizer table. I can’t figure how to arrange the Equalizer table to preserve the symmetry. As far as I can tell, my real and imaginary Equalizer table are symmetric. So why can’t I get a clear output ?
Complete code:
Fs = 16000; % sampling frequency
no_samples = 640; % no of samples
Freq1 = 1000; % Frequency 1 of the signal
Freq2 = 2500; % Frequency 2 of the signal
Freq3 = 3500; % Frequency 3 of the signal
Amp = 0.1;
t = 1/Fs*((1:no_samples)-1); % time duration, t = 1/Fs
Input_sig_16k = Amp*sin(2*pi*Freq1*t)+Amp*sin(2*pi*Freq2*t)+Amp*sin(2*pi*Freq3*t); % Multitone Input Signal
% Equlizer data
Eq_data_32 =[0.0;0.1347;0.2117;0.2956;0.4146;0.5300;0.5615;0.5195;0.4391;0.3621;0.2816;0.1977;0.1837;0.1172;0.0857;0.0577;0.0;0.0577;0.0857;0.1172;0.1837;0.1977;0.2816;0.3621;0.4391;0.5195;0.5615;0.5300;0.4146;0.2956;0.2117;0.1347];
re_Eq_data_32 = Eq_data_32; % Equalizer data for real values
im_Eq_data_32 = -(re_Eq_data_32);
window_size = 32;
for ii = 1:(length(Input_sig_16k)/window_size)-1
data_range = (((ii-1)*window_size)+1:((ii-1)*window_size)+32);
data_block = Input_sig_16k(data_range);
fft_sig = fft(data_block); %FFT of the signal
after_eq_re = real(fft_sig).*re_Eq_data_32'; % Multiply real portion of FFT with Equalizer
after_eq_im = imag(fft_sig).*im_Eq_data_32'; % Mutliply imaginary portion with Equalizer
after_eq = after_eq_re + (i*after_eq_im);
ifft_sig = ifft(fft_sig); %iFFT of the signal
data_full(data_range) = ifft_sig; % Output signal
end
plot(Input_sig_16k,'-og'), grid on; % plot and compare both the signals
hold on;
plot(data_full,'-xr')
hold off;
Multiplication in the frequency domain is circular convolution in the time domain. Circular convolution means that the end of your multiplication filtering process wraps around and corrupts the beginning of each FFT/IFFT buffer.
Instead, zero-pad each FFT by at least the length of the impulse response of your equalization filter. Then use either overlap-add or overlap-save (fast convolution methods/algorithms) to re-combine your IFFT results.
Also, if you want a strictly real result (no non-zero imaginary numbers), make sure that the input to your IFFT is conjugate symmetric.

DFT code on Matlab does not work as intended

I am trying to implement a basic DFT algorithm on Matlab.
I simply use in phase and quadrature components of a sine wave with phase modulation(increasing frequency a.k.a chirp). I do compare my results with fft command of Matlab. My code gives the same results whenever there is no phase modulation(pure sine). Whenever I add chirp modulation, results differ. For example, when I use a chirp with some bandwidth around a carrier, the expected results should be a frequency distribution of chirp bandwidth starting from carrier frequency. However, I get a copy of that result backwards starting from carrier frequency as well. You can use my code below without modifying anything. Figure 5 is my result and figure 6 is the expected result. Carrier is 256 Hz with a 10Hz bandwidth of chirp. You can see the code below. The important part is for loop where I take dft of my signal. Also uou can see my dft result below.
close all;
clear all;
%% signal generation
t = (0:0.0001:1); % 1 second window
f = 256; %freq of input signal in hertz
bw = 10; % bandwidth sweep of signal
phaseInput = 2*pi*t*bw.*t;
signalInput = sin(2*pi*f*t + phaseInput); %input signal
inphase = sin(2*pi*f*t).*cos(phaseInput); %inphase component
quadrature = cos(2*pi*f*t).*sin(phaseInput); %quadrature component
figure
plot(t,signalInput,'b',t,inphase,'g',t,quadrature,'r');
title('Input Signal');
xlabel('Time in seconds');
ylabel('Amplitude');
%% sampling signal previously generated
Fs = 1024; %sampling freq
Ts = (0:1/Fs:1);%sample times for 1 second window
sPhase = 2*pi*Ts*bw.*Ts;
sI = sin(2*pi*f*Ts).*cos(sPhase);
sQ = cos(2*pi*f*Ts).*sin(sPhase);
hold on;
plot(Ts,sI+sQ,'b*',Ts,sI,'g*',Ts,sQ,'r*');
fftSize = Fs; %Using all samples in dft
sampleIdx = (0:1:fftSize-1)';
sampledI = sI(1:fftSize)';
sampledQ = sQ(1:fftSize)';
figure;
plot(sampleIdx,sampledI,sampleIdx,sampledQ);
title('Sampled IQ Components');
%% DFT Calculation
dftI = zeros(fftSize,1);
dftQ = zeros(fftSize,1);
for w = 0:fftSize-1
%exp(-2*pi*w*t) = cos(2*pi*w*t) - i*sin(2*pi*w*t)
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
end;
figure;
plot(Fs*sampleIdx/fftSize,dftI);
title('DFT Inphase');
xlabel('Hertz');
figure
plot(Fs*sampleIdx/fftSize,dftQ);
title('DFT Quadrature');
xlabel('Hertz');
figure;
plot(Fs*sampleIdx/fftSize,sqrt(dftQ.^2+dftI.^2));
%% For comparison
sampledInput = sin(2*pi*f*Ts + sPhase);
Y = fft(sampledInput(1:1024),1024);
Pyy = Y.*conj(Y)/1024;
f = (0:1023);
figure;
plot(f,Pyy)
title('Power spectral density')
xlabel('Frequency (Hz)')
the reason lies in the fact that two different signals will definitely give your two different frequency spectrums. check out the code below, you will find that the input of the dft algorithm you actually gave is sampledI+jsampledQ. as a result, what you are doing here is NOT merely decomposing your original signal into In-phase and quadrature components, instead, you are doing Hilbert transform here -- to change a real signal into a complex one.
cI = cos(2*pi*w*sampleIdx/fftSize); %correlation cos
cQ = -sin(2*pi*w*sampleIdx/fftSize); %correlation sin
dftI(w+1) = sum(sampledI.*cI - sampledQ.*cQ); %
dftQ(w+1) = sum(sampledI.*cQ + sampledQ.*cI);
so the sampledInput for comparison should be sampledInput = sI+1i*sQ;.

Graphing the Short-time Fourier Transform (note the window size and step) in matlab

Need help since kind of lost on this. I am trying to graph the code below i have in which I made a white noise and used STFT to do the bandpass filtering but now I need to graph the signal in to two graphs for each channel. The result should be graphs. For graph 1a., the horizontal axis should be frequency, the vertical axis should be amplitude. For (2).b, the horizontal axis should be time, the vertical axis should be frequency, and express the amplitude using color.
function newwhitenoise()
L = 5000; %Sample length for the random signal
Pause = 10000; %Sample Pause Gap
mu = 0;
sigma = 2;
%Need to see left signal is not displaying
Left_signal = sigma*randn(L,1) + mu;
Right_signal = sigma*randn(L,1) + mu;
Long_signal = [Left_signal zeros(L,1); zeros(Pause,2); zeros(L,1) Right_signal];
%Player Object
soundRecord(Long_signal);
disp([Left_signal zeros(L,1)]);
%sound(Long_signal, Fs);
%Plots subplots in graph
%figure
%subplot(211);
%plot(Left_signal, 'b'); grid on;
%subplot(212);
%plot(Right_signal, 'r'); grid on;
end
function signalplayer(signal)
%load(signal);
fs = 44100; %Sample Frequency
obj = audioplayer(signal,fs);
play(obj);
end
function soundRecord (signal)
fs = 44100; %Sample Frequency
recObj = audiorecorder(44100, 16, 2);
get(recObj)
%save sound to wave file
%filename = 'location.flac';
audiowrite('input.wav',signal, fs);
if ~exist('inFile')
inFile = 'input.wav';
end
if ~exist('outFile')
outFile = 'output.wav';
end
if ~exist('frameWidth')
frameWidth = 4096; % size of FFT frame, better be a power of 2
end
frameHop = frameWidth/2;
analWindow = hanning(frameWidth);
[inBuffer, Fs] = wavread(inFile);
x = [inBuffer(:,1); linspace(0, 0, frameWidth)']; % use left channel only, zeropad one frame at the end
clear inBuffer;
numSamples = length(x);
numFrames = floor(numSamples/frameHop)-1;
% disp(frameWidth);
% disp(numSamples);
% disp(frameHop);
% disp(numFrames);
% disp(size(analWindow));
% disp(size(transpose(analWindow)));
y = linspace(0, 0, numSamples)';
n = 0; % init sample pointer. unlike MATLAB, i like counting from 0
for frameIndex = 1:numFrames
xWindowed = x(n+1:n+frameWidth) .* analWindow; % get and window the input audio frame
X = fft(fftshift(xWindowed)); % do the FFT
Y = X; % copy the input spectrum to output
% do whatever processing to Y that you like
yWindowed = fftshift(real(ifft(Y))); % convert back to time domain, toss the imaginary part
%disp(size(x(1:frameWidth)));
%disp(size(yWindowed));
y(n+1:n+frameWidth) = y(n+1:n+frameWidth) + yWindowed;
n = n + frameHop;
end
wavwrite(y, Fs, 'output.wav');
For graph 1 try pwelch and for graph 2 try spectrogram.
pwelch is basically the average of the squared magnitude of the STFT. The spectrogram function returns the STFT of the signal thus it operates on the signal in the time domain.
Both functions are called with the same input parameters and when called with no output, plot the result on the current axes.
If you want the frequency axis to be the vertical (y) in graph 2, use the option 'yaxis' in the call for spectrogram. I suggest you look at the documentation of both functions.