Electronics > Metrology

FFT measurements, DC bin and Power

(1/3) > >>

I needs to implement some measurements on ADC sampled data with FFT (such as dBm power in selected bandwidth, etc), and I stuck with one question.

Let's assume that load R=1. So, the power of a sine waveform signal with a peak amplitude A can be calculated as:

Power = A^2 / 2

but at the same time power of DC signal can be calculated as:

Power = A^2

This is because DC signal is constant, so it has constant power and don't needs to be averaged over full cycle with positive and negative part of the waveform.

I'm not sure, may be I'm wrong, but at a glance it seems that a magnitude of DC bin in the FFT result needs to be corrected in order to get proper power value, or at least it needs to be handled in a different way than other FFT bins. I think that such correction is required because FFT DC bin represents constant signal and other FFT bins represents sine carriers.

I asked chat-gpt and he said that I'm correct and DC bin of FFT needs to be corrected for a proper power measurements. But strange thing that I didn't hear about such correction before, so I'm not sure if such correction is relevant for FFT spectrum measurements.

So, I wonder when such correction is needed and when it is not for a spectrum measurements with FFT? What is the best practice?

To be sure, I'm talking about signal which is represented according to AES17 standard meaning, where signal is symmetric around zero value and minimum negative code is not used. So, full scale sine has 0 dBFS level and full scale square wave has +3.01 dBFS level.

And now I'm not sure what is the level of DC signal with maximum positive amplitude? And what is the power of such DC signal?

gf:
Consider that there is only one bin for DC and one for Nyquist, but the power of other frequencies is split into positive and negative frequency bins.

EDIT: The sum of the power of the time domain samples is the same as the sum of the power of all (positive and negative!) frequency bins.

Example:

--- Code: --->> N=100;
>> signal=rand(1,N);      % a random real signal
>> spectrum=fft(signal);  % corresponding (complex) FFT spectrum

% power sum of time domain samples
>> sum(signal.**2)
ans =  32.211

% power sum of spectrum
>> sum(spectrum.*conj(spectrum))/N
ans =  32.211

% power sum of spectrum (alternative calculation method)
>> sum(abs(spectrum).**2)/N
ans =  32.211

--- End code ---

MasterT:

--- Quote from: radiolistener on March 29, 2023, 05:59:29 pm ---I needs to implement some measurements on ADC sampled data with FFT (such as dBm power in selected bandwidth, etc), and I stuck with one question.

Let's assume that load R=1. So, the power of a sine waveform signal with a peak amplitude A can be calculated as:

Power = A^2 / 2

but at the same time power of DC signal can be calculated as:

Power = A^2

--- End quote ---

You confused A , for AC signal A is peak voltage this is why division by 2 comes. Shoud be RMS, than in both cases DC or AC formula is the same P = A^2
P = Ap-p ^2 / 2 = (A-rms * sqrt(2)) ^2 / 2 = A-rms ^2.
Correction is not required if all magnitudes inside bines are considered as RMS values.

gf:

--- Quote from: radiolistener on March 29, 2023, 05:59:29 pm ---So, I wonder when such correction is needed and when it is not for a spectrum measurements with FFT? What is the best practice?

--- End quote ---

If you discard the negative frequency bins and consider only the positive ones, then you need to double the power of each bin (in order to account for the power in the discarded negative frequency counterparts), but don't double the power of the DC and the Nyquist bins (which exist only once and do not have negative frequency counterparts).

Here is MATLAB test code, I added 3 test vectors - sine wave, square wave and DC (two of them are commented):

--- Code: ---Fs = 128;
N = 128;
t = 0:1/Fs:(N-1)/Fs;

signal = sin(2*pi*2*t);                         % sine wave
%signal = cat(2, ones(1, N/2), -ones(1, N/2));  % square wave
%signal = ones(1, N) * 1;                       % DC wave

spectr = fft(signal);

psignal = sum(signal.^2)/N;
pspectr = sum(abs(spectr/N).^2);

fprintf('psignal = %f = %+.2f dBFS\n', psignal, 20*log10(psignal));
fprintf('pspectr = %f = %+.2f dBFS\n', pspectr, 20*log10(pspectr));

--- End code ---

the output for sine wave is:

--- Code: ---psignal = 0.500000 = -6.02 dBFS
pspectr = 0.500000 = -6.02 dBFS
--- End code ---

As we see power in time and freq domain are the same which is ok.
But according to AES17 standard, it should be 0 dBFS for sine wave with max amplitude.

How to fix calcualtions to get correct results for AES17 standard?

If assume that 0.5 is a power of a full scale sine wave, we can try to divide power with 0.5 to get level relative to a full scale sine:

--- Code: ---psignal = (sum(signal.^2)/N) / 0.5;
pspectr = (sum(abs(spectr/N).^2)) / 0.5;
--- End code ---

For sine wave it shows 0 dBFS as expected. For square wave and DC it shows the same value +6.02 dBFS. So it looks that there is no need to use correction for DC bin.

But as I remember AES17 standard mention that square wave with max amplitude has +3.01 dBFS level:

--- Quote ---3.3.1
decibels, full scale
dB FS
amplitude expressed as a level in decibels relative to full-scale amplitude (20 times the common logarithm of the amplitude over the full-scale amplitude)
NOTE The rules of the International System of Units (SI) require that a space appear after the standard symbol dB.

3.4
full-scale signal level
FS
signal amplitude relative to the full-scale amplitude expressed in decibels, full scale or percent, full scale
NOTE Because the definition of full scale is based on a sine wave, it will be possible with squarewave test signals to read as much as + 3,01 dB FS. Square-wave signals at this level are not recommended because tilt or overshoot introduced by any filtering operations will cause clipping of the signal.
--- End quote ---

so I'm not sure where is mistake.

Update: just notice, that AES17 talking about signal level as amplitude...
so I tried to get sqrt to get amplitude from power:

--- Code: ---asignal = sqrt(sum(signal.^2)/N);
aspectr = sqrt(sum(abs(spectr/N).^2));

fprintf('asignal = %f = %+.2f dBFS\n', asignal, 20*log10(asignal));
fprintf('aspectr = %f = %+.2f dBFS\n', aspectr, 20*log10(aspectr));

--- End code ---

it shows the following result:

--- Code: ---asignal = 0.707107 = -3.01 dBFS
aspectr = 0.707107 = -3.01 dBFS

--- End code ---

So, I divided it with 0.707107 (full scale amplitude):

--- Code: ---asignal = sqrt(sum(signal.^2)/N) * sqrt(2);
aspectr = sqrt(sum(abs(spectr/N).^2))  * sqrt(2);

--- End code ---

and it shows expected result:

--- Code: ---asignal = 1.000000 = +0.00 dBFS
aspectr = 1.000000 = +0.00 dBFS
--- End code ---

for both - square wave and DC it shows:

--- Code: ---asignal = 1.414214 = +3.01 dBFS
aspectr = 1.414214 = +3.01 dBFS
--- End code ---

is this correct?