Time-Frequency Analysis
Est. read time: 1 minute | Last updated: July 06, 2025 by John Gentile
Contents
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from rfproto import impairments, plot, sig_gen
Fourier-Based Analysis Methods
Short-Time Fourier Transforms (STFTs)
# simulate random binary input values
num_symbols = 2**15
num_disp_sym = 16
sym_rate = 1e6 # Baseband symbol rate
# Generate random QPSK symbols
rand_symbols = np.random.randint(0, 4, num_symbols)
L = 4 # Upsample ratio (Samples per Symbol)
fs = L * sym_rate # Output sample rate (Hz)
rolloff = 0.25 # Alpha of RRC
num_filt_symbols = 6 # Symbol length of RRC matched filter
qpsk_tx_filtered = sig_gen.gen_mod_signal(
"QPSK",
rand_symbols,
fs,
sym_rate,
"RRC",
rolloff,
num_filt_symbols,
)
noise = impairments.awgn(-34, len(qpsk_tx_filtered))
print(max(qpsk_tx_filtered))
print(max(noise))
fig, ax = plt.subplots()
Pxx, freqs, bins, im = ax.specgram(qpsk_tx_filtered + noise, NFFT=8192, Fs=fs)
plt.show()
(0.4421523309681831+0.3187446908836157j) (0.06516204736822895-0.0011955606920690848j)
Polyphase Filter Bank (PFB) Channelizers
For higher quality spectral analysis than STFT methods, one should use a filterbank approach instead of a windowed FFT. Put simply, the STFT approaches use a single multiplication per sample at the input of the FFT- a channelizer uses a polyphase filter for each input. With PFB filtering, much better spectral separation is achieved between the FFT bins compared to just windowing.
For more info, see the Multirate DSP page on PFB Channelizers.