Reputation: 23
I tied the Matlab function snr
which is part of the signal processing toolbox since R2013b. As described in the Matlab documentation this function accepts the power spectral density (PSD) estimate as input. I though: 'This is cool! This means that I can calculate the SNR even if I don't know what the noise looks like.'
However the snr
function gives another result than the standard equation for SNR caclulation, which is SNR = 10 * log10(mean(signal.^2) / mean(noise.^2))
. The difference is about 6 dB.
It seems that the PSD estimations with both pwelch and fft smoothen the noise too much, so the noise power becomes smaller than it should be. How can I get a more accurate estimation with snr
?
Here is my code:
rng default
fs = 50e3;
sourceSig = sin(linspace(0,1,fs) .* 2 * pi * 100);
noise = 0.5 * rand(size(sourceSig));
noisySig = sourceSig + noise;
% calc SNR using equation
sigPow_check = 10 * log10(mean(sourceSig.^2)); % signal power
noisePow_check = 10 * log10(mean(noise.^2)); % noise power
SNR_check = sigPow_check - noisePow_check;
fprintf('\n calculation with equation: \n')
fprintf('SNR: %.2f dB \n', SNR_check)
fprintf('noise power: %.2f dB \n', noisePow_check)
fprintf('signal power: %.2f dB \n', sigPow_check)
% calc SNR using snr function and PSD, PSD estimated with pwelch
[pxx_1, f1] = pwelch(noisySig,[],[],[],fs);
[SNR_1, noisePow1] = snr(pxx_1,f1,'psd'); % in dB
fprintf('\n estimation with pwelch and snr: \n')
fprintf('SNR: %.2f dB \n', SNR_1)
fprintf('noise power: %.2f dB \n', noisePow1)
fprintf('signal power: %.2f dB \n', SNR_1+noisePow1)
% calc SNR using snr function and PSD, PSD estimated with fft
N = length(noisySig);
xdft = fft(noisySig);
xdft = xdft(1:N/2+1); % one sided spectrum
pxx_2 = ((1/(fs*N)) * abs(xdft).^2)'; % PSD
pxx_2(2:end-1) = 2*pxx_2(2:end-1); % scale
f2 = (0:fs/N:fs/2)'; % freq vector
[SNR_2, noisePow2] = snr(pxx_2,f2,'psd'); % in dB
fprintf('\n estimation with fft and snr: \n')
fprintf('SNR: %.2f dB \n', SNR_2)
fprintf('noise power: %.2f dB \n', noisePow2)
fprintf('signal power: %.2f dB \n', SNR_2+noisePow2)
The console outut is:
calculation with equation:
SNR: 7.79 dB
noise power: -10.80 dB
signal power: -3.01 dB
estimation with pwelch and snr:
SNR: 13.77 dB
noise power: -16.77 dB
signal power: -3.00 dB
estimation with fft and snr:
SNR: 13.81 dB
noise power: -16.81 dB
signal power: -3.01 dB
Upvotes: 2
Views: 1294
Reputation: 1550
Your input noise is incorrect. By using noise = 0.5 * rand(size(sourceSig));
, the function rand
will produce positive random numbers and this very uncommon as noise. Algorithms might give unexpected results. Do you really intend to work with a non centred noise?
I suggest you center your noise:
a = 0.5;
noise = (a*rand(size(sourceSig)))-a/2;
Results are:
calculation with equation:
SNR: 13.80 dB
noise power: -16.81 dB
signal power: -3.01 dB
estimation with pwelch and snr:
SNR: 13.78 dB
noise power: -16.78 dB
signal power: -3.00 dB
estimation with fft and snr:
SNR: 13.81 dB
noise power: -16.81 dB
signal power: -3.01 dB
You can also try randn
to produce a Gaussian Noise.
Upvotes: 2