DSP Icebreaker – Adding white noise to signals, the proper way.

This article is in addition to the last article where we saw how to plot a sinusoidal wave using python. In this article we will see how can we add noise to signals. And later we will see the power of filters by removing our added noise.

Noise is a unwanted disturbance in the signal. When we are trying to simulate our system, we want to model our system as close to real world as possible. It is for this purpose we are trying out this exercise.

At first we may think that how hard can it be to add noise. One can simply think that generating a random number and adding to the signal would be enough.
Well you maybe right, this will distort the signal, and that’s the way it is done anyways; but it gets tricky when we are asked to quantify the noise added, i.e. how much is the noise added?

So we will start with basics.

Noise Measurement –

Gaussian Noise :

It is the simplest of all the method used to represent noise. Partly because of two important reasons –
1. Very mathematical friendly probability distribution function.
2. Closely represents the actual world.
To further simplify we set the mean to be zero so that it maybe called Zero Mean Gaussian Noise.
If one is not so familiar with the concept of noise, this might be good time to brush up.

Consider a row matrix-

N being the number of sample or size of matrix. Each number ‘x(i)‘ is a random variable (i.e. can take any value) and is independent of other elements of matrix.
Let ‘u‘ be the mean of all the numbers of ‘X’. This is same as E[X].
Let v’ be the variance of X. This is simply E[square( (X-u)) ] .
For zero mean Gaussian Noise, the above matrix has u = 0. Then if u = 0, v is nothing but the power contained in the signal.
Such a noise signal has 0 DC component and has only AC component.

Signal to Noise Ratio –

The ratio of signal power to noise power is called SNR. SNR is mostly represented in dB (decibel) scale. This is given as

Where S is the signal power and N is noise power.
For a sinusoidal signal, S is given as –

And N is nothing but variance for zero mean signal.

This essentially simplifies into-

in dB scale,

Now , consider that our sinusoidal signal has unity amplitude. We want a target sinusoidal wave that has SNR to be 40.
To achieve this, we have to adjust noise power in such a way that SNR_db is 40.
This gives that noise power has to be adjusted in this way –

e.g. If SNR_db = 40, S = 1, then N = 0.39.

Now we have the the noise power. To generate the noise signal which has above noise power, we will use Python’s uniform random number generator function.
In this we will set mean = 0, and variance as our power obtained in above system.

The noise generated is directly added to sinusoidal signal, as our Gaussian noise is additive in nature.

See the python code for this and analyze the results

import numpy as np
import matplotlib.pyplot as plot

numSamples = 100

# ----------------------------------------------------------
# sine wave of 100 Hz, sampling freq 1000 Hz

fs = 1000
fm = 100

time        = np.arange(0, numSamples, 1);
amplitude   = np.sin(2*np.pi*fm / fs * time)
signalPower = np.sum(np.square(amplitude))/np.size(amplitude)

print("amplitude size", np.size(amplitude))

# ----------------------------------------------------------
# SNR of 40 dB
# SNR in db means 10log(Psignal/Pnoise)
snrDb = 40

# key is to find noise power such that signal power is 
# 40 dB more 
# 40 = 10 log (Ps / Pn)
# 10^40 = Ps / Pn
# Pn is variance which for zero mean gaussian noise 
# is essentially - square sum of all samples -> divided by numSamples
noiseVar = signalPower / np.power(10, snrDb / 10) 

# generate the noise of the variance
noiseMean = 0
stdNoise = np.sqrt(noiseVar)
samples = np.random.normal(noiseMean, stdNoise, size=numSamples)
print("noise size", np.size(samples))

# ----------------------------------------------------------
# recalculate SNR - for verification
noise_power_100_samples = np.sum(np.square(samples))/np.size(samples)
SNR = 10*np.log10(1 / noise_power_100_samples)
print("SNR:", SNR)

# ----------------------------------------------------------
# add the Noise to the signal
noisySignal = np.add(samples, amplitude)
print("noisy signal size", np.size(noisySignal))

# ----------------------------------------------------------
# plot the signal
plot.plot(time, noisySignal)

# Give a title for the sine wave plot
plot.title('Sine wave + 40 dB noise')

# Give x axis label for the sine wave plot
plot.xlabel('Time')

# Give y axis label for the sine wave plot
plot.ylabel('Amplitude = sin(time)')
plot.grid(True, which='both')
plot.axhline(y=0, color='k')
plot.show()

We can also verify that the SNR which is calculated from the signal is even close to required SNR or not.

Play around with the SNR values and see how the signal varies with changing SNR.

And we are done!

Leave a comment