简体   繁体   中英

How to get a accurate estimation with Matlab function snr()?

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 

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM