Field Guide · concept

Also known as: real-time DSP, streaming DSP, real-time signal processing

Real-time DSP is digital signal processing that must keep up with a continuous sample stream — finishing the work for each block of samples before the next block arrives — so the system never falls permanently behind the rate at which data is produced.1 For a software radio the deadline is set by the sample rate: at 2.4 MS/s the pipeline has, on average, well under a microsecond of compute budget per sample, and missing that budget for too long means dropped data, not merely a slow answer.

each window = one block's worth of samples over deadline → buffer backs up, then overruns keeping up
As long as each block finishes inside its window the system holds real time; a block that overruns its window pushes the backlog up until the buffer overflows.

How it works

Real-time DSP is organized around throughput first, then latency. The unbreakable requirement is that the average processing rate meet or exceed the sample rate — if it doesn’t, the backlog in the sample buffer grows without bound until it overflows into an overrun. A ring buffer between the source and the DSP absorbs short-term jitter: a block that runs a little long is fine as long as later blocks catch up and the buffer drains again. What is fatal is a sustained deficit.

Most SDR work is soft real time: an occasional missed deadline degrades quality (a lost decode) but is tolerable, unlike a hard real-time controller where a single miss is a failure. To hold the deadline, real-time DSP code avoids anything with unpredictable timing on the hot path:

  • No blocking I/O in the processing loop — disk writes, network sends, and logging move to separate threads fed through queues.
  • No unbounded allocation — buffers are pre-allocated and reused so memory management doesn’t inject pauses (a particular concern under a garbage collector).
  • Bounded, predictable kernels — fixed-size FFTs, filters, and loops whose cost per block is known, so the budget can actually be reasoned about.

In practice

Two levers relieve a pipeline that can’t keep up. The first is doing less work: decimate early so later stages run at a lower rate, choose the smallest sample rate the signal needs, and pick efficient algorithms. The second is parallelism: multithreaded DSP splits stages across cores so a slow stage doesn’t stall the whole chain, at the cost of added latency and synchronization. Deep buffers trade latency for robustness against jitter; shallow buffers give tight latency but leave no slack. The right balance depends on whether a human is listening live or a decoder is merely logging.

Relevance to SDR

Every live receiver is a real-time DSP system: tune, filter, demodulate, and decode must all clear before the ADC’s next batch lands. Offline replay from a file is not real-time — the file source will wait — which is precisely why file-based development is easier and reproducible, and why a bug that only appears live often points at timing or resource contention rather than the math.

GopherTrunk is a real, pure-Go SDR application built around this discipline. It streams IQ through buffers the decoders drain independently, sizes those buffers to ride out scheduling jitter, and exposes a dropped-sample counter so a real-time miss surfaces as a visible overrun instead of a silent glitch. Being written in Go means GT also has to keep allocation off the hot sample path so garbage collection doesn’t threaten the deadline. Notably, its decode chain is rate-invariant — it normalizes each protocol to a fixed channel rate regardless of capture rate — so the real-time budget is governed by that channel rate and the CPU, and the offline .cfile path can reproduce a live decode without any real-time deadline at all.

Sources

  1. Real-time computing — Wikipedia, on hard vs soft real-time deadlines and deadline-bound processing. 

See also