# FFT scaling consistency

**URL:** <https://www.ruby-forum.com/t/fft-scaling-consistency/233237>\
**Category:** GNU Radio\
**Created:** [November 26, 2014, 10:39am UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237 "2014-11-26T10:39:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [November 26, 2014, 10:39am UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/1 "2014-11-26T10:39:54Z")

</div>

Hi,

Yesterday someone in the chat raised an interesing issue. The absolute  
scale of the various FFT GUI sinks.

If you take:

[signal source ampl=1.0] -\> [gui fft sink]

(use a source freq that fits exactly on 1 fft bin)

With complex + WXGUI it peaks at -3dB  
With complex + QTSink it peaks at -9dB  
With float + WXGUI it peaks at -9dB  
With float + QTSink it peaks at -15dB

So basically:

- The WXGui + Complex should be 0dB IMHO.  
A complex cosine of ampl 1.0 should be our ‘absolute’ reference for  
0dB

- QTSink is always 6dB lower  
-\> That doesn’t sound logical, they should just match. GUI  
selection should have no influence on the absolute reading when  
working with purely synthetic data.

- Float is always 6dB lower than complex  
-\> I’m torn on this one … can’t decide 😛  
If you integrate the energy (x^2) over one cycle between a  
complex cosine and a float cosine, you get half the energy. So this  
should be -3 dB right ? And I guess the other 3dB comes from the fact  
that half of this energy is in the positive spectrum and half of it in  
the negative one (so if you take the total energy in the whole  
spectral domain, it does indeed match the one in the time domain) ?  
The question is then, when displaying a float fft, should we  
just raise by 3dB ?

Anyway, I hope this make sense 😛

Thoughts ?

Cheers,

```
Sylvain
```

---

<div class="post-metadata">

**Author:** ![Sylvain\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/839c29/32.png) [@Sylvain\_M](https://www.ruby-forum.com/u/Sylvain_M)\
**Post date:** [November 26, 2014, 11:36am UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/2 "2014-11-26T11:36:57Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Hi Sylvain,

at first I hm’ed, but then I hm!ed.  
So, first thing, yes, using a single tone as reference does sound  
logical, especially since it’s so intuitive from an analysis point of  
view, considering RX signals to be a sum of weighted complex sinusoids.

Then: no, QT GUI does that, see [1] (generated by [2]). The tone at  
samp\_rate / fft\_length \* 10 has a power of 0 dB; also, Gaussian noise  
with an amplitude of 1 has an average (picture is heavily averaged)  
power of -20 dB == 1/fft\_length. Perfect!

To the complex vs. real discussion: Picture [3] tells me that I see  
the noise at -23 dB; now, this will get extremely philosophical  
whether when observing a real signal this should be -20 dB instead. I  
like to think of it as “don’t add energy when you don’t specify where  
that comes from, or you’ll end up building virtual perpetuum mobiles”:  
The real noise can be considered complex noise with $\Im{x} \equiv 0$,  
so it logically has less energy than the complex circular gaussian  
noise of [1]. If we display it having as much energy as the latter,  
we’re acting as if we knew that the imaginary part wasn’t zero. That  
can’t end well, especially when looking at stuff like SNRs.

Cheers,  
Marcus

[1] [http://marcus.hostalia.de/test\_fft\_power.png](http://marcus.hostalia.de/test_fft_power.png)  
[2] [http://marcus.hostalia.de/test\_fft\_power.grc](http://marcus.hostalia.de/test_fft_power.grc)  
[3] [http://marcus.hostalia.de/fft\_test\_real.png](http://marcus.hostalia.de/fft_test_real.png) (please ignore the  
complex sinusoid label. It’s a plain-as-water real sine.)

On 11/26/2014 10:38 AM, Sylvain M. wrote:

> (use a source freq that fits exactly on 1 fft bin)
> 
> total energy in the whole spectral domain, it does indeed match the
> 
> Sylvain
> 
> \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ Discuss-gnuradio  
> mailing list [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [Discuss-gnuradio Info Page](https://lists.gnu.org/mailman/listinfo/discuss-gnuradio)

-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1

iQEcBAEBAgAGBQJUdazVAAoJEAFxB7BbsDrLhggH/11fQd8mBrvYqM1i+DDSKs0o  
gxqqAMvUSbcURtWnYdU13HI9bOb3CcpApcHKjxITg+D8l+Qkb7KB3xmrNui85Ko2  
vsS56QPHuTnfefdhZaKZw7OFQ+OTzMVd0Wfe2Gfi9NCuHvR37b8NABfIfViYdmO3  
W9zdpSIZ14VXZXfaB/WS+MB4y2Z4leRNIBSeg54IAhn5PAS9Y8AEYy4w4qKsXDqd  
31/8P0aN3W4rvApPkV8E2jBQ/nNqq7ZJxl/oK4MKmW3oLaQYhkAs5uHhOGZhFgTj  
YMKq3pgqlSccTJQ/2g+5iGEwN+IaOw46/Y9AhPfa5eTrrVR4+c26ouUueSGTCX8=  
=eNmU  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![Sylvain\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/839c29/32.png) [@Sylvain\_M](https://www.ruby-forum.com/u/Sylvain_M)\
**Post date:** [November 26, 2014, 12:09pm UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/3 "2014-11-26T12:09:07Z")

</div>

Hi,

> Then: no, QT GUI does that, see [1] (generated by [2]). The tone at  
> samp\_rate / fft\_length \* 10 has a power of 0 dB; also, Gaussian noise  
> with an amplitude of 1 has an average (picture is heavily averaged)  
> power of -20 dB == 1/fft\_length. Perfect!

Oh, that’s interesting.

I didn’t see that when I did the test here. Turns out it’s the window  
selection, if you select Rectangular, you have 0dB and it’s consistent  
between WX and Qt.

If you select something else, then it’s no longer 0dB and it becomes  
inconsistent between the WX and Qt widgets.  
Now obviously windowing will have some effect on the peak value, but:

- I didn’t expect it to be this large, I expected more like a few  
tenth of dB, not precisely 3 or 6dB.
- I certainly don’t see why Wx or Qt would make a difference

> To the complex vs. real discussion: Picture [3] tells me that I see  
> the noise at -23 dB; now, this will get extremely philosophical  
> whether when observing a real signal this should be -20 dB instead.

Yes, it’s definitely more of a philosophical question than anything  
else.  
Honestly I don’t really care either way, I just though I’d bring this  
up at the same time and see if there was a “convention” that was  
expected.

Cheers,

```
Sylvain

```

---

<div class="post-metadata">

**Author:** ![Sylvain\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/839c29/32.png) [@Sylvain\_M](https://www.ruby-forum.com/u/Sylvain_M)\
**Post date:** [November 26, 2014, 1:07pm UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/4 "2014-11-26T13:07:22Z")

</div>

On 11/26/2014 12:07 PM, Sylvain M. wrote:

> If you select something else, then it’s no longer 0dB and it becomes  
> inconsistent between the WX and Qt widgets.  
> Now obviously windowing will have some effect on the peak value, but:
> 
> - I didn’t expect it to be this large, I expected more like a few  
> tenth of dB, not precisely 3 or 6dB.

The peak loss is a function of the window length and its type. You can  
calculate the value by:

loss = 1/(N \* l2\_norm(w)) \* |\sum\_{n=0}^{N-1} w(n)|^2

…hope my pseudo-latex makes sense 🙂

For a blackman-harris window, it’s very close to 3 dB for most window  
lengths. For complex, you’re applying it twice, though, hence the  
difference.

> - I certainly don’t see why Wx or Qt would make a difference

That must be a bug or something. Looks like the WX results are closer to  
the truth.

M

---

<div class="post-metadata">

**Author:** ![Sylvain\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/839c29/32.png) [@Sylvain\_M](https://www.ruby-forum.com/u/Sylvain_M)\
**Post date:** [November 26, 2014, 4:33pm UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/5 "2014-11-26T16:33:19Z")

</div>

I normalized the wx complex display a long time ago. As you have  
discovered, windowing affects this, but in two separate ways. First,  
windowing reduces total signal power because most bins are less than 1.  
We  
normalize for that, so the total energy remains constant. You will see  
that if you run with awgn.

The second issue is spreading energy into adjacent bins. This will  
affect  
anything you expected to remain in one bin, like a sine wave. There  
isn’t  
any way to fix this as its not broken. To find the power in a sine  
you’ll  
need to add the power of several adjacent bins.

Matt

---

<div class="post-metadata">

**Author:** ![Sylvain\_M](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/839c29/32.png) [@Sylvain\_M](https://www.ruby-forum.com/u/Sylvain_M)\
**Post date:** [November 26, 2014, 12:38pm UTC](https://www.ruby-forum.com/t/fft-scaling-consistency/233237/6 "2014-11-26T12:38:51Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

Hi,

at least Window scaling differing between QT and WX is in fact a bit  
irritating…

Cheers 🙂

Marcus

On 11/26/2014 12:07 PM, Sylvain M. wrote:

> window selection, if you select Rectangular, you have 0dB and it’s
> 
> > To the complex vs. real discussion: Picture [3] tells me that I
> 
> Sylvain

-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1

iQEcBAEBAgAGBQJUdbtlAAoJEAFxB7BbsDrLzggH/0AwVlFLkoGBdmwqRrrQkW17  
YDoXMpk/RMKRwYECoXYw/mr4tDk2OqwwM2I9IfLQwb/tWc7YF5ocXipbtJMdb4tL  
yiaISddiEyspcT/7KAwNeRYXU61dFPCJBkp9+2TI/kGoH6qIDM4+fW5C3dkQqeaa  
SdVQMWySWNAmtYBoyxOyGem7UWamNOPw9cVCpcGV3xbmjw/IJGm9DZgHLJ5fwSUA  
Epzy+D+XGflfPQlpFoeuGw7zo21/PN6BP+OxFaL7eFk1YYgiYcXeS/kl1AENxQkE  
OnGy2y7lQOqCJe7SAGArARANp1x5926yXM4aS9keUUFsGqT/uoATvUis6i/O+8c=  
=TuxP  
-----END PGP SIGNATURE-----
