Add random noise with specific SNR to a signal - matlab

I have randomly generated signal for example:
%frequency
f1 = 1000; f2 = 2000;
Fs = 8000; %sampling frequency
%amplitudes
amp1 = 0.75;
amp2 = 0.2;
%time
dt = 1/Fs
stopTime = 0.3;
t = 0:dt:stopTime;
%random noise
noise = randn(1,length(t))
%generated signal
Signal = amp1*sin(2*pi*f1*t) + amp2*sin(2*pi*f1*t) + noise;
Now i need to create two Signals S1, S2 with random noise with specific SNR.
Noise added to S1 must be uncorrelated with noise added to S2
Here is what i tried:
%SNR in dB
SNR = [-80,-40,-20,0,20,40,80];
%S1,S2 = Signal + rand noise with SNR -40dB
S1 = awgn(Signal,SNR(2),'measured')
S2 = awgn(Signal,SNR(2),'measured')
Is this correct approach to create random noise with SNR from range -80dB to +80dB? will noise added to S1 be uncorrelated with noise added to S2?

You could just calculate variance of signal and add noise with variance required to produce desired SNR. Here is some python code as an example
import scipy as sp
import scipy.fftpack as fft
# frequency
f1 = 1000.0
Fs = 8000.0 # sampling frequency
# amplitudes
amp1 = 0.75
# time
n = sp.arange(1024)
# Desired SNR in dB
SNR_dB = 40
# Desired linear SNR
snr = 10.0**(SNR_dB/10.0)
print "Linear snr = ", snr
# Measure power of signal
signal1 = amp1*sp.sin(2*sp.pi*f1/Fs*n)
p1 = signal1.var()
print "Power of signal1 = ", p1
# Calculate required noise power for desired SNR
n = p1/snr
print "Noise power = ", n
print "Calculated SNR = %f dB" % (10*sp.log10(p1/n))
# Generate noise with calculated power
w = sp.sqrt(n)*sp.randn(1024)
# Add noise to signal
s1 = signal1 + w
will noise added to S1 be uncorrelated with noise added to S2?
Yes.

Related

Matlab FFT: Power Spectral Density or Amplitude Spectral Density?

The amplitude of a FFT should be depending on the length of the signal.
To display the result in a independent way the Power Spectral Density or the Amplitude Spectral Density should be used. There are calculated as follows:
Amplitude FFT = Y
Signal Length = L
Power Spectral Density PSD = Y^2/L
Amplitude Spectral Density ASD = Y/sqrt(L)
https://www.sjsu.edu/people/burford.furman/docs/me120/FFT_tutorial_NI.pdf
My problem is, that the result of the Matlab fft is already indipendent from the signal length and I do not understand if this is already a PSD or a ASD.
Let's take the Matlab example Noisy Signal: https://ch.mathworks.com/help/matlab/ref/fft.html
If we make the FFT on the same signal, but twice or ten times longer, the FFT amplitude does not change.
This because of the line:
P2 = abs(Y/L);
where the amplitude is divided through the signal length. But why is the formula different from the PSD or the ASD formula and we still obtain amplitudes indipendent from the signal length?
In this example it is shown, that the two signals, ones for 50s, ones for 500s, has almost the same amplitudes.
% Signal 1
sps = 1000; % Sampling frequency
T = 1/sps; % Sampling period
Frequency1 = 150; % frequency 1 [Hz]
SignalAmplitude1 = 1; % mm/s
Frequency2 = 45; % dominant frequency [Hz]
SignalAmplitude2 = 1.2; % mm/s
L = 50; % Length of signal, sek.
L = L*1000; % convert to ms
time = (0:L-1)*T; % Time vector
Signal = cos(2*pi*Frequency1*time)*SignalAmplitude1 + sin(2*pi*Frequency2*time)*SignalAmplitude2;
f = sps*(0:(L/2))/L;
FFTcomplex = fft(Signal);
P2 = abs(FFTcomplex)/L;
P1 = P2(:,round(1:L/2+1));
P1(:,2:end-1) = 2*P1(:,2:end-1);
Ampl_FFT_1 = P1;
% Signal 2
sps = 1000; % Sampling frequency
T = 1/sps; % Sampling period
Frequency1 = 150; % frequency 1 [Hz]
SignalAmplitude1 = 1; % mm/s
Frequency2 = 45; % dominant frequency [Hz]
SignalAmplitude2 = 1.2; % mm/s
L = 500; % Length of signal, sek.
L = L*1000; % convert to ms
time = (0:L-1)*T; % Time vector
Signal = cos(2*pi*Frequency1*time)*SignalAmplitude1 + sin(2*pi*Frequency2*time)*SignalAmplitude2;
f = sps*(0:(L/2))/L;
FFTcomplex = fft(Signal);
P2 = abs(FFTcomplex)/L;
P1 = P2(:,round(1:L/2+1));
P1(:,2:end-1) = 2*P1(:,2:end-1);
Ampl_FFT_2 = P1;
sum(Ampl_FFT_2)-sum(Ampl_FFT_1)

matlab Band-pass Filter not working

I try to simulate a noisy signal and Filter it. the signal mix some low frequency signals and some random noise. my goal is to get 14.8Hz signal.
my band-pass bandwidth is 14.7Hz to 14.9Hz.
function filteringTest
Hd = KaiserFilter;
Fs = 4000; % Sampling frequency
T = 1/Fs; % Sample time
L = 40000; % Length of signal
t = (0:L-1)*T; % Time vector
r1 = 320;
r2 = 575;
y = 50*sin(2*pi*14.8*t) + r1*sin(2*pi*14.7*t) + r2*sin(2*pi*15.1*t) + 10.1*rand(size(t));
yfilter = filter(Hd.Numerator,1,y);
plot(yfilter)
function Hd = KaiserFilter
Fs = 4000; % Sampling Frequency
N = 4096; % Order
Fc1 = 14.7; % First Cutoff Frequency
Fc2 = 14.9; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
Beta = 0.5; % Window Parameter
% Create the window vector for the design algorithm.
win = kaiser(N+1, Beta);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
my signal image is :
and filter result is :
when i try to increase Filter Order from 4096 to 32*4096 , i get this result :
why this filter do not work correct? do i chage my filtering method?
what should i do to get 14.8Hz frequency signal?
thanks.
Why is your sampling rate so high? Reduce your sampling rate and use a notch filter to take out a selective frequency. I have re-written some sections of your code:
Fs = 200;
desiredFrequency = 14.8;
[b,a] = NotchFilter(Fs, desiredFrequency)
In the filter definition, you can do this:
function [b,a] = NotchFilter(Fs,desiredFrequency)
w = desiredFrequency/(Fs/2);
[b,a] = iirnotch(w,w/400);
Now perform the filtering
y_filter = filtfilt(b,a,y);
desiredSignal = y-y_filter;
plot(desiredSignal,'LineWidth',2); hold on; plot(y,'LineWidth',2)
You'll see something like this.

Random Noise Effect On Signal Filtering in Matlab

I'm woking on signal processing and Filtering. i create a noisy signal and i want to use bandpass filter to get my desire frequency.
i generate noisy signal "y" by this code :
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
r = a + (b-a).*rand(1,1);
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
and i filter my signal to get 15.5 Hz signal by FIR algorithm like Chebyshev. i use FDATool to design bandpass filter. like this :
Fs = 16000; % Sampling Frequency
N = 16 * 4096; % Order
Fc1 = 15.48; % First Cutoff Frequency
Fc2 = 15.52; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
SidelobeAtten = 100; % Window Parameter
% Create the window vector for the design algorithm.
win = chebwin(N+1, SidelobeAtten);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
and use filter function in matlab to get my desire signal :
filteredSignal = filter(Hd.Numerator,1,y);
max_amp = max(filteredSignal );
and after filtering i get maximum of signal amplitude. it is work fine. but there is a big problem for me.
because of random noise i have diffrent values of filtered signal max.
like : 10.552 , 10.493 , 10.876 , 10.524 , 10.617
and when i decrease value of random noise like this :
r = 0.001;
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
i get this values of filterd signal maximum like :
10.541 , 10.541 ,10.541 , 10.541, 10.541
and now my question is :
how to reduce or decrease noise effect on my filtered signal? what should i do for get same value of max amplitude of signal after filtering?
thanks.
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 200000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
r = a + (b-a).*rand(1,1);
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
N = 16 * 4096; % Order
Fc1 = 15.48; % First Cutoff Frequency
Fc2 = 15.52; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
SidelobeAtten = 100; % Window Parameter
% Create the window vector for the design algorithm.
win = chebwin(N+1, SidelobeAtten);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
filteredSignal = filter(Hd.Numerator,1,y);
Testim=1/15.5;
t0=0;
Ts=1/Fs;
steadyData=filteredSignal(100001:200000);
numAvr=100;
samLen=length(steadyData)/numAvr;
m=[];
for j=0:numAvr-1;
s0=steadyData(1+j*samLen:j*samLen+samLen);
Omega=fminbnd('jomega',(2*pi/Testim)*.9,(2*pi/Testim)*1.1, [0,1.0e-30 ], s0,t0,Ts);
[Amplitude,Theta,RMS]=sinefit2(s0,Omega,t0,Ts);
freq=Omega/(2*pi);
if 15.4<=freq & freq<=15.6
m=[m Amplitude];
else
end
end
avrAmp=(1/length(m))*sum(m)
I don't know what you want to do, exactly. But, in order to reduce noise effect hear, we could use least square method, if we know some information, such as frequency, sampling rate, etc. I give you an example.You can find the function 'sinefit2.m' at "http://www.mathworks.com/matlabcentral/fileexchange/3730-sinefit". I think, after fitting, the amplitude would be commonly more similar, but not always.
If you want to get always same amplitude, you should fix your random number. whenever you run your code, matlab will generate different random number, and SNR will be changed. The one way fixing random number is to initialize random number generator.
Please try following code.
Fs = 16000; % Sampling frequency
fNy = Fs / 2;
T = 1/Fs; % Sample time
L = 60000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 12.6 , 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*12.6*t);
x1 = 15.3 * sin(2*pi*15.5 * t );
a = 5.2;
b = 35.5;
rng(0,'twister')
r = a + (b-a).*rand(1,1);
rng(0,'twister')
y = x + x1 + r*randn(size(t)); % Sinusoids plus noise
plot(y)
With these code you could see always the same signal y.

Confused with fft Matlab

I am little bit confused with fft. That would be good if anyone can help me. first, I want to convert fft output in time domain. Where t = f/k and K = BW/Tm (BW = bandwidth & Tm = transmit time). After that again i need to take fft and ouput should be box (rectangular function) which is having width of BW(40e9).
f1 = 1e6; % first cutoff frequency
f2 = 4e6; % second cutoff frequency
BW = 40e9; % bandwidth
Tm = 0.2e-3; % transmit time
fs = 1e7; % sampling frequency
c = 3e8; % speed of light
w1 = f1/ (fs/2); % normalizing first cutoff frequency
w2 = f2/ (fs/2): % normalizing second cutoff frequency
[b,a] = butter(2, [w1,w2], 'bandpass');
load('fb2040');
x = fb2040(3,:);
y_filt = filter(b,a,x); % filtering
nfft = length(y_filt);
res = fft(y_filt, nfft)/ nfft;
f = fs/2 * linspace(0,1,nfft/2+1);
res = res(1:nfft/2+1);
figure, plot(f,abs(res));
xlabel('frequency in MHz');
ylabel('amp');
return

MATLAB: : Mean square error vs SNR plot

I am having difficulty in understanding the logic behind generating a plot of SNR (db) vs MSE. Different Signal to Noise Ratio (SNR) is created by varying the noise power . The formula of MSE is averaged over T independent runs.
For each SNR, I generate NEval = 10 time series. How do I correctly plot a graph of SNR vs MSE when SNR is in the range = [0:5:50]? Below is the pseudo code.
N = 100; %Number_data_points
NEval = 10; %Number_of_different_Signals
Snr = [0:5:50];
T = 1000; %Number of independent runs
MSE = [1];
for I = 1:T
for snr = 1: length(Snr)
for expt = 1:NEval
%generate signal
w0=0.001; phi=rand(1);
signal = sin(2*pi*[1:N]*w0+phi);
% add zero mean Gaussian noise
noisy_signal = awgn(signal,Snr(snr),'measured');
% Call Estimation algorithm
%Calculate error
end
end
end
plot(Snr,MSE); %Where and how do I calculate this MSE
As explained here (http://www.mathworks.nl/help/vision/ref/psnr.html) or other similar sources, MSE is simply the mean squared error between the original and corrupted signals. In your notations,
w0=0.001;
signal = sin(2*pi*[1:N]*w0);
MSE = zeros(T*Neval,length(Snr));
for snr = 1:length(Snr)
for I = 1:T*Neval %%note, T and Neval play the same role in your pseudo code
noisy_signal = awgn(sin(2*pi*[1:N]*w0+rand(1)),Snr(snr),'measured');
MSE(I,snr) = mean((noisy_signal - signal).^2);
end
end
semilogy(Snr, mean(MSE)) %%to express MSE in the log (dB-like) units
For the case of signals of different lengths:
w0=0.001;
Npoints = [250,500,1000];
MSE = zeros(T,length(Npoints),length(Snr));
for snr = 1:length(Snr)
for ip = 1:length(Npoints)
signal = sin(2*pi*[1:Npoints(ip)]*w0);
for I = 1:T
noisy_signal = awgn(sin(2*pi*[1:Npoints(ip)]*w0+rand(1)),Snr(snr),'measured');
MSE(I,ip,snr) = mean((noisy_signal - signal).^2);
end
end
end
semilogy(Snr, squeeze(mean(mean(MSE,1),2)) )