sig_pwr=sum(X(bin_start:bin_end).*conj(X(bin_start:bin_end)));
quantize_signal=floor((no_quantiz_levels-1)*signal)+no_quantiz_levels/2
window_type=hann(N)';
window_scaling_factor=sum(window_type);
Why are you dividing the signal power by 3?signal_value = ((sum((abs(fft_signal(Nw:Nw+2))).^2))/3)
I also noticed that you are only taking half of the signal power and half of the noise power (two errors that cancel each other so, no harm there).
I also noticed that you are only taking half of the signal power and half of the noise power (two errors that cancel each other so, no harm there).
close all;
clear all;
% Generate a simulation signal
fin = 257;
fs = 8192;
N = 8192;
adc_resolution = 16; % Or Quantizer resolution
Nw = floor((fin*N)/fs);
amp = 0.499;
signal = amp*sin(2*pi*Nw/N*[0:N-1]);
figure(1);
subplot (2,1,1);
plot(signal);
title('Original Signal');
ylabel('Signal Amplitude');
xlabel('Time');
% Scalar quantization is implemented over here
no_quantiz_levels = power(2, adc_resolution);
quantize_signal=floor((no_quantiz_levels-1)*signal)/(no_quantiz_levels/2);
subplot (2,1,2);
plot(signal-quantize_signal/2, 'g*');
title('Quantization error');
% FFT and SNR measurement
% Remember that hann window reduces the amplitude of the signal to half in
% frequency domain and that is why scaling is done by N/4 instead of N/2
window_type=ones(1,N);%hann(N)'; %Coherent sampling, no need for windowing
window_scaling_factor=sum(window_type);
fft_signal = fft(quantize_signal.*window_type,N)*(2/window_scaling_factor);
freq_scal = linspace (0, 0.5, N/2); % for normalized frequency
X=fft_signal.*conj(fft_signal);
figure(2);
plot(freq_scal, 10*log10(X(1:N/2)), '-x');
hold on
plot(freq_scal(Nw:Nw+2), 10*log10(abs(fft_signal(Nw:Nw+2))), 'r*');
title('FFT Plot (N = 8192, Hann window is used)');
xlabel('Frequency (Normalized)');
signal_value = (sum(fft_signal(Nw:Nw+2).*conj(fft_signal(Nw:Nw+2))))
noise_bins = [fft_signal(2:fin-1) fft_signal(fin+3:N/2)];
noise = (sum((abs(noise_bins)).^2)) / ((N/2)-3)
noise = 2*(sum(noise_bins.*conj(noise_bins)))
noise_formula = ((1/power(2,adc_resolution))^2)/12
SNR = 10*log10(signal_value/noise)
SNR_byQuantizationFormula = 10*log10(signal_value/noise_formula)
noise = 2*(sum(noise_bins.*conj(noise_bins)))
Below is how I modified your code. As you can see, your "SNR_byQuantizationFormula" gives an incorrect result for a 16 bit quantizer (6.02*adc_resolution+1.76=98.1dB, your formula gives 107.1dB).My result,95.1dB, is closer but not correct yet.I will keep looking, as I have some spare time...Code:close all; clear all; % Generate a simulation signal fin = 257; fs = 8192; N = 8192; adc_resolution = 16; % Or Quantizer resolution Nw = floor((fin*N)/fs); amp = 0.499; signal = amp*sin(2*pi*Nw/N*[0:N-1]); figure(1); subplot (2,1,1); plot(signal); title('Original Signal'); ylabel('Signal Amplitude'); xlabel('Time'); % Scalar quantization is implemented over here no_quantiz_levels = power(2, adc_resolution); quantize_signal=floor((no_quantiz_levels-1)*signal)/(no_quantiz_levels/2); subplot (2,1,2); plot(signal-quantize_signal/2, 'g*'); title('Quantization error'); % FFT and SNR measurement % Remember that hann window reduces the amplitude of the signal to half in % frequency domain and that is why scaling is done by N/4 instead of N/2 window_type=ones(1,N);%hann(N)'; %Coherent sampling, no need for windowing window_scaling_factor=sum(window_type); fft_signal = fft(quantize_signal.*window_type,N)*(2/window_scaling_factor); freq_scal = linspace (0, 0.5, N/2); % for normalized frequency X=fft_signal.*conj(fft_signal); figure(2); plot(freq_scal, 10*log10(X(1:N/2)), '-x'); hold on plot(freq_scal(Nw:Nw+2), 10*log10(abs(fft_signal(Nw:Nw+2))), 'r*'); title('FFT Plot (N = 8192, Hann window is used)'); xlabel('Frequency (Normalized)'); signal_value = (sum(fft_signal(Nw:Nw+2).*conj(fft_signal(Nw:Nw+2)))) noise_bins = [fft_signal(2:fin-1) fft_signal(fin+3:N/2)]; noise = (sum((abs(noise_bins)).^2)) / ((N/2)-3) noise = 2*(sum(noise_bins.*conj(noise_bins))) noise_formula = ((1/power(2,adc_resolution))^2)/12 SNR = 10*log10(signal_value/noise) SNR_byQuantizationFormula = 10*log10(signal_value/noise_formula)
---------- Post added at 08:57 PM ---------- Previous post was at 08:43 PM ----------
As I copied and pasted the code, I notices that I left a "2*" in the noise calculation:That "2*" is redundant because the signal power is calculated on half of the spectrum... so, the SNR is actually correct: 98.1dB!Code:noise = 2*(sum(noise_bins.*conj(noise_bins)))
---------- Post added at 09:23 PM ---------- Previous post was at 08:57 PM ----------
Here is the last bit of information.
Using your notation, the noise formula is incorrect: the rms quantization error is Pnoise_rms=VLSB/sqrt(12), where VLSB is VREF/2^N, VREF=1, in your case.
The rms power of a full-scale sinewave is: Psignal_rms=VREF/(2*sqrt(2)). The SNR is than calculated as 20*log10(Psignal_rms/Pnoise_rms).
In matlab:
noise_formula = (1/2^adc_resolution)/sqrt(12)
SNR_byQuantizationFormula = 20*log10((2*amp/sqrt(8))/noise_formula)
I hope this helps!
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?