I was wondering if anyone could provide some insight on how to calculate the SNR of low frequency baleen whale calls? Matlab has a SNR function,but when I try that it doesn't seem to be capturing the frequencies of interest for the call. I included spectrograms of the calls I'm interested in. One is a Rice's whale long-moan call and the other is a downsweep pulse sequence of the same species.
-
$\begingroup$ Could you share which parameters you used with the Matlab SNR function please? $\endgroup$– NoilJul 22, 2022 at 23:24
-
1$\begingroup$ Sure all I did was snr(x,Fs) where x is a 30s window centered on the call (from a 30 min wav file -also used that to make the spectrogram) and Fs is is 2000. This is the output I get, but I know the fundamental frequency it's focusing on isn't the long-moan call since it's too low $\endgroup$– atcook65Jul 25, 2022 at 16:53
-
$\begingroup$ @atcook65 comments can disappear over time and are often ignored. Could you edit your question directly to include the settings specified in your comment? $\endgroup$– seleneJul 28, 2022 at 15:11
1 Answer
Estimating SNR means first estimating the (background) noise. The two spectrograms are great as they emphasize that in most cases signal would be hidden in background noise when displayed as broadband time series.
One solution is: working in spectrogram domain and quick answer is:
[~,F,T,P]=spectrogram(xx,hann(nw),no,nfft,fs);
N=median(P,2);
SNR=sqrt(P./N);
The median approximates the noise estimate for a reasonable noise window reducing the influence of a spiky signal. If you have a noise window without the signal then you would use
N=mean(P,2);
P and N are in terms of spectral power (here: power spectral density PSD), so in order to get a amplitude-based SNR by taking the sqrt.
SNR is here a spectral matrix.
Note: I'm using Matlab 2019a, so that "./" works properly even if P is a matrix and N is a vector.
If you wanted to work in the time domain, then you must bandpass filter your data to remove the out-of-interest noise.
For pulse sequences in your data you can then still use the median approach
nn=median(xx);
snr=xx/nn;
or if you know that xxo is data without signal (e.g. 1 or 2 seconds before signal) then you can use
nn=std(xxo);
snr=(xx-mean(xx))/nn;
snr is here a time vector.