Radio RF spectrum

The FFT, Part 1: Time, Frequency, and the Magic of I/Q

An introduction to the foundational math behind Software Defined Radio, exploring the time domain, the frequency domain, and why I/Q sampling is essential for the Fast Fourier Transform.

By Matt Weaver
Oct 20, 2026
14 min read

Demystifying Digital Signal Processing for Software Defined Radio

If you have been following my recent projects, you might have noticed a slight shift in focus. For a long time, much of my digital signal processing (DSP) work centered around clean audio pipelines, active noise cancellation, and echo reduction tailored for virtual meetings. Lately, however, I have stepped away from microphone arrays and corporate meeting rooms to spend more quality time at my amateur radio bench.

My primary playground has been the sBitx v3, a fascinating open-source, Raspberry Pi-powered HF SDR (Software Defined Radio) transceiver made by HF Signals. Working directly on the sBitx v3 software stack is a refreshing change of pace. Instead of processing spoken human voices, I am dealing with raw radio frequencies spanning the shortwave spectrum. Mostly to process spoken human voices…

To make sense of the RF environment on an SDR display, to render those crisp spectrum analyzers and glowing waterfall displays, you need one fundamental tool: the Fast Fourier Transform (FFT).

In this series, we are going to break down how the FFT works under the hood and why it is indispensable for modern radio enthusiasts. We’ll dive into what the FFT is, how it’s used, and the concrete example of how we can apply that knowledge to substantially improve part of the sBitx’s software.

This is one of those areas where amateur radio and general audio processing have a lot of overlap, so hopefully there’s something here for hams and remote workers, alike.

Let’s start at the absolute beginning: how hardware sees signals versus how radio operators see them.


1. The Time Domain: What the Hardware Sees

When a radio wave hits your antenna, it induces a tiny, continuously varying electrical voltage. To process this signal digitally, an SDR passes that analog voltage through an Analog-to-Digital Converter (ADC).

Most SDRs actually run through at least one stage before this, to do things like filter the signal a bit, and narrow down the range of frequencies the ADC has to convert. A really nice radio can receive the entire HF spectrum, from 3MHz all the way up to 30 MHz, or even more. The sBitx isn’t that nice. The software sees a 48 kHz-wide slice of radio spectrum from the ADC, and only about two thirds of that is actually usable.

The ADC samples the voltage at fixed intervals, converting the smooth continuous wave into a discrete stream of numbers over time. This is the Time Domain.

A discrete stream of voltage samples forming a sine wave in the time domain

To the hardware, there are no “stations,” no “modes,” and no “bandwidths.” The ADC does not inherently know that a signal is a Morse code carrier or a SSB voice transmission. It simply records a sequence of snapshots:

[ 0.00, 1.41, 2.00, 1.41, 0.00, -1.41, -2.00, -1.41, … ]

While raw time-domain data is easy to capture and store, it is extremely difficult to analyze visually or algorithmically if you want to find a specific signal in a crowded band.

Note: Don’t care about radios, but you care about audio? Guess what! From here on out, it’s basically the exact same thing! All of the concepts apply just as well to the audio frequency spectrum (0 Hz to 20 kHz) as they do to the radio frequency spectrum! In fact, when the software receives the signal from the ADC, the signals has been shifted from whatever it was at (say, from 7.050 MHz to 7.098 MHz) down to 0 Hz to 48 kHz, which is the exact same frequency range you’d expect in an audio project running at a sample rate of 98 kbps! I believe the sBitx even uses a regular sound card for its ADC.

This is especially useful for learning and illustrative purposes, since you can easily experiment with tools designed for audio.


2. The Frequency Domain: How Operators Think

As ham radio operators (and office workers, and musicians, and really just humans in general), we rarely think in terms of instantaneous microvolts. We think in terms of frequencies. We want to know:

  • Where are the sharp, narrow CW (Continuous Wave, AKA Morse) signals?
  • Where are the 3 kHz-wide Single Sideband (SSB) voice signals?
  • What does the noise floor look like across an entire 40-meter or 20-meter band segment?

To answer these questions, we need to view our signals in the Frequency Domain. Instead of showing how voltage changes over time, the frequency domain shows how much energy (power) exists at each specific frequency at a given moment.

A spectrum analyzer view of the frequency domain showing a broad SSB “voice” hump and a razor-sharp CW needle spike rising from the background noise floor (note: voice on SSB doesn’t really look like that, but this illustrates the idea)

This is the view you see in every spectrum analyzer you’ve ever run across in your life. Showing you time-domain informaton in the frequency domain is what they do.

The anatomy of a panadapter

Above, we have an illustration of a Panadapter. A panadapter is a tool for viewing some portion of the radio frequency spectrum in the frequency domain. The bumpy part at the top is the spectrum analyzer. Below that, the waterfall shows how the spectrum has changed over the last few seconds (when seen live, it scrolls down from the spectrum analyzer, vaguely resembling a waterfall on acid, hence the name).

Note how they provide both a live view of what’s happening right now and a short history of what’s been happening. You can also see things outside of what the radio operator is actually hearing (the yellow shaded area on the left); in this case, they are hearing the SSB signal but not the CW signal. You can see how wide each separate signal is, and what its overall shape, width, length, etc are; a CW, SSB, or RTTY signal look radically different from each other. Also notice how the background of the waterfall is not solid black, but has a grainy, slightly dark blue look to it. That’s the noise floor in the background, which could be mostly caused by actual environmental noise from outside the radio or it could be internal noise coming from inside the radio itself.

Fourier’s Breakthrough

The bridge between these two perspectives is built on a mathematical theorem formalized by Joseph Fourier in the early 19th century: Fourier’s Theorem, which states that any complex, repeating waveform can be represented as the sum of a series of simple, pure sine waves, each with its own specific amplitude, phase, and frequency.

The mathematical operation that takes us from the raw time-domain sample stream to the organized frequency-domain spectrum is the Discrete Fourier Transform (DFT).

It’s analogous to looking at a square drawn on a piece of paper. From directly above, you see a square. Tilt your head, and it’s more of a diamond. From another angle, it turns into an rectangle, diamond, etc. It’s the same information, just viewed from different perspectives. The frequency and time domains are just different, but equivalent, perspectives from which you can view the frequency spectrum.

Unfortunately, a DFT isn’t particularly feasible for computers. It’s expensive to calculaate and it tends to produce an infinite set of output data for a finite set of input data. Fortunately, we also have its high-speed algorithmic cousin, the Fast Fourier Transform (FFT).

The FFT takes as its input a time-domain series of values and breaks it up into a finite set of “bins” that each represent a narrow band of frequencies. It’s not the smooth line you think of in a spectrum analyzer, but it’s analogous (in fact, spectrum analyzers generally operate on these bins, but smoothed out, to give the illusion that it’s a DFT when it’s not).

Key insight: digital signal processing (DSP) algorithms nearly always operate on blocks of time-domain data, rather than on the constant stream of numbers coming from the ADC. They might process 1024 numbers at once as input, output a result, and then pull in the next block of 1024 numbers.

Crucially, the number of numbers (aka samples) in a block is generally constant, as is the number of bins being used for FFTs in a system. When you use the same value for both of these, you get an interesting result: you can generally jump back and forth between the time and frequency domains without losing any information! Technically, you do tend to filter the signal a little bit when you do the FFT to go back and forth, so it’s not a perfectly lossless process, but it’s close enough.

The human ear can hear a roughly 20 kHz wide range of frequencies, and can distinguish tones that are incredibly close together (especially at lower frequencies). You could take a complex piece of music, represent it as 10 different sine waves (one for each bin), then convert it back into the time domain, and you’d get that piece of music back out. Neat!

With a frequency-domain signal, you can operate directly on the frequencies themselves, rather than relying on the much more complex math that operates in the time domain. For example, if you want to lower the treble on a frequency-domain signal, you can simply lower the value of the higher frequency bins before you turn it back into a time-domain signal.

Want to reduce the background noise? One common approach is to set a minimum threshold for the bins, and then zero out any bin that is below that threshold (that is basically how the sBitx’s “DSP” noise reduction algorithm works).

This idea of FFTing to the frequency domain, operating on the signal, and then Inverse-FFTing (IFFT) it back to the time domain is the fundamental idea that drives a very large portion of the sBitx’s software implementation. This surprisingly efficient process is called Fast Convolution.

You can stop here.

That wraps up the core concepts I wanted to cover in this post, so feel free to stop reading if you want. From here, it gets a bit more nerdy (somehow) and is interesting to me, but it’s not terribly important. This was just something that took me a while to wrap my head around when I was introduced to software defined radios, so maybe someone else can benefit from my experience. Or they’ll get more confused. Whatever.


3. The Software Problem: Baseband Folding

If you run a single stream of real-valued numbers straight from the ADC into your processing pipeline, you eventually run into a massive mathematical car crash known as “baseband folding.”

To understand why this happens, we have to look at how the sBitx pulls a signal from the air into the software.

Inside your transceiver, there is a frequency generator called a Local Oscillator (LO). Think of it as the tuning dial. If you want to listen to a conversation on the 40-meter band, you might want to center your radio on 7.050 MHz.

The sBitx uses a “superheterodyne” architecture, meaning it doesn’t tune the hardware LO exactly to 7.050 MHz. Instead, it tunes it exactly 24 kHz lower, to 7.026 MHz. The hardware mixer subtracts this 7.026 MHz LO from all the radio waves hitting the antenna. This shifts the incredibly fast radio frequencies down to much lower audio frequencies (an Intermediate Frequency (IF)) that a standard audio codec can digitize.

Let’s look at two signals hitting the antenna at the same time:

  • Signal A is transmitting at 7.055 MHz (5 kHz above your target). It mixes down to 29 kHz.
  • Signal B is transmitting at 7.045 MHz (5 kHz below your target). It mixes down to 19 kHz.

When the ADC digitizes this, there is no ambiguity. The hardware perfectly preserved the separation: Signal A is sitting at 29 kHz, and Signal B is at 19 kHz. The hardware hands the software a clean, single-channel, real-valued audio stream.

Here is where the problem starts.

Digital Signal Processing algorithms hate working on signals offset by an arbitrary 24 kHz IF. The math is vastly easier, faster, and more efficient if your target frequency (7.050 MHz) is shifted to sit exactly at 0 Hz (Baseband).

To shift the entire digitized spectrum down to 0 Hz, the software has to subtract 24 kHz from everything. Let’s look at what happens if we just use normal, real numbers to do that shift:

  • The 29 kHz signal (Signal A) shifts down by 24 kHz and happily becomes +5 kHz.
  • The 19 kHz signal (Signal B) shifts down by 24 kHz and mathematically becomes -5 kHz.

Real numbers cannot represent negative frequencies. When a real number goes negative in this context, it “folds” over the zero line. That -5 kHz signal becomes a +5 kHz signal.

Boom. Signal A and Signal B just crashed into each other in the exact same +5 kHz space. The software can no longer tell them apart.

To shift to 0 Hz without folding the spectrum in on itself, a single real number from the ADC is not enough. We need two-dimensional numbers. We need I/Q data.


4. The Magic of I/Q Data (And the Software Quadrature Mixer)

To safely shift our signals down to 0 Hz, the sBitx employs a Digital Down-Converter (DDC). It essentially acts as a massive software quadrature mixer, replacing physical hardware components with pure C code.

Instead of just mathematically subtracting 24 kHz, the software builds a fake, mathematical Local Oscillator. It uses a phase accumulator and a lookup table to generate perfect digital waves, and multiplies the incoming audio stream by two of them simultaneously:

  1. In-Phase (I): The incoming stream is multiplied by a digital cosine wave.
  2. Quadrature (Q): The incoming stream is multiplied by a digital, inverted sine wave (shifted 90 degrees from the cosine).

Because the Q channel is phase-shifted by 90 degrees relative to the I channel, the combined pair forms a complex number. By tracking the signal across both axes (I and Q), the software can track the rotation of the signal.

Frequency DirectionPhase RelationshipVisual Rotation
Positive Frequency (+f)I leads Q by 90°Counter-clockwise vector rotation
Negative Frequency (-f)Q leads I by 90°Clockwise vector rotation

By converting the signal to complex numbers as it shifts down by 24 kHz, the math preserves the negative frequency space. Signal A stays at +5 kHz (rotating counter-clockwise), and Signal B successfully becomes -5 kHz (rotating clockwise). No folding. No crashing.

A complex plane diagram showing an I/Q sample point plotted with In-Phase on the X axis, Quadrature on the Y axis, and the resulting vector illustrating Amplitude and Phase

The Cleanup: The FIR Filter

There is one final math quirk to clean up. When you multiply two 24 kHz frequencies together (our IF stream and our digital LO), trigonometry dictates that you don’t just get the difference (0 Hz), you also get the sum (48 kHz).

If you feed that 48 kHz mathematical trash into an FFT, it will completely ruin your panadapter display and filters. So, immediately after the I and Q streams are generated, the sBitx software runs them both through a digital FIR (Finite Impulse Response) low-pass filter. The filter lets the clean 0 Hz baseband signals pass right through, but aggressively scrubs out the 48 kHz artifacts.

Only after passing through this digital mixer and filter does the software finally have the clean, two-dimensional complex data it needs.


Summary and Next Steps

By taking a real-valued signal, mathematically mixing it against digital sine and cosine waves, and filtering the output, the sBitx software successfully constructs a continuous stream of complex numbers centered cleanly at 0 Hz baseband. This I/Q stream contains all the raw mathematical material required to reconstruct the complete RF spectrum without mirror images, folding, or lost signal directions.

Here is how the pipeline connects so far:

  1. Antenna & Hardware Mixer: Captures physical RF energy and mixes it down to a 24 kHz Intermediate Frequency.
  2. Digitization: The ADC samples the voltage into a single stream of discrete, real numbers.
  3. Digital Down-Conversion: The software mathematically mixes the real numbers down to 0 Hz baseband using digital Cosine/Sine waves, creating paired In-Phase (I) and Quadrature (Q) complex numbers.
  4. FIR Filtering: A software low-pass filter scrubs out high-frequency mathematical artifacts.
  5. The FFT (Next Up): Transforms that complex time-domain stream into discrete frequency bins to build the panadapter display and apply digital filters.

In Part 2, we will dive into the math and mechanics of the Fast Fourier Transform itself, exploring how we go from these raw sample blocks to the responsive spectrum analyzers and waterfalls we rely on in platforms like the sBitx v3.