# basic FFT normalization questions

I'm using Matlab to take FFTs of signals, and I'm getting stuck on the normalization. Specifically, how to normalize the spectrum into units of dBm. I know that 0.316228 is the correct normalization factor, but my questions are related to how to normalize the bins correctly.

I created the following program to raise my questions. Just cut and paste it into Matlab and it'll run itself. See questions in-line.

In particular, I'm confused how to normalize the bins. For example, if the FFT has indices 1:end, where end is even, when I calculate the FFT magnitude spectrum, should I multiply by (2/N) for indices 2:(end/2)? Similarly, does the bin at the Nyquist frequency (located at index end/2+1) get normalized to (1/N)? I know there's a bunch of ways to normalize depending on one's interest. Let's say the signal I'm using (St below) are voltages captured from an ADC.

Any feedback is greatly appreciated. Thanks in advance!

``````%% 1. Create an Example Signal
N = 2^21 ;                   % N = number of points in time-domain signal (St)
St = 1 + rand(N,1,'single'); % St = example broadband signal (e.g. random noise)

% take FFT
Sf = fft(St, N);
Sf_mag = (2/N)*abs(Sf(1: N/2 + 1));
Sf_dBm = 20*log10(Sf_mag / 0.316228); % 0.316338 is peak voltage of 1 mW into 50 Ohms

% Q: Are Sf_mag and Sf_dBm normalized correctly? (assume 0.316338 is correct
%    peak voltage to get 1mW in 50 Ohms)
% Q: Should Sf_mag(fftpoints/2 + 1) = (1/N)*abs(Sf(fftpoints/2 + 1) for correct normalization
%    of Nyquist frequency? (since Nyquist frequency is not folded in frequency
%    like the others are)

%% 2. Plot Result

% create FFT spectrum x-axis
samplerate = 20e9;  % 20 Gsamples/sec
fft_xaxis = single(0 : 1 : N/2)';
fft_xaxis = fft_xaxis * single(samplerate/N);

semilogx(fft_xaxis, Sf_dBm, 'b-')
xlabel('Frequency (Hz)');
ylabel('FFT Magnitude (dBm)');
title('Spectrum of Signal (Blue) vs Frequency (Hz)');
xlim([1e4 1e10]);
grid on;
``````
-
Use `log10` instead of `log` when converting the mag to dB – YYC Oct 29 '10 at 22:08
Yup, that's a great find YYC, Thanks! – ggkmath Oct 30 '10 at 18:32

Do `fft([1 1 1 1])`. Do `fft([1 1 1 1 1 1 1 1])`. In particular, observe the output magnitude. Is it what you expect?
Then do `fft([1 -1 1 -1])`. Do `fft([1 -1 1 -1 1 -1 1 -1])`. Repeat for various signal lengths and frequencies. That should allow you to normalize your signals accordingly.
Also, do the same thing for `ifft` instead of `fft`. These are good sanity checks for various FFT implementations, because while most implementations may put the `1/N` in front of the inverse transform, others may put `1/sqrt(N)` in front of both forward and inverse transforms.
{"found_math": false, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "url": "http://stackoverflow.com/questions/4055921/basic-fft-normalization-questions?answertab=votes", "fetch_time": 1369430761000000000, "content_mime_type": "text/html", "warc_filename": "crawl-data/CC-MAIN-2013-20/segments/1368705069221/warc/CC-MAIN-20130516115109-00057-ip-10-60-113-184.ec2.internal.warc.gz", "warc_record_offset": 259367272, "warc_record_length": 11632, "token_count": 805, "char_count": 2708, "score": 3.5, "int_score": 4, "crawl": "CC-MAIN-2013-20", "snapshot_type": "latest", "language": "en", "language_score": 0.83873450756073, "file_path": "/sailhome/yjruan/project/latent-lm/data/processed/finemath-4plus/finemath-4plus/train-00003-of-00064.parquet"}