OFDMDemodulator#

class sionna.phy.ofdm.OFDMDemodulator(fft_size: int, l_min: int, cyclic_prefix_length: int | numpy.ndarray | torch.Tensor = 0, precision: Literal['single', 'double'] | None = None, device: str | None = None, **kwargs)[source]#

Bases: sionna.phy.block.Block

Computes the frequency-domain representation of an OFDM waveform with cyclic prefix removal.

The demodulator assumes that the input sequence is generated by the TimeChannel. For a single pair of antennas, the received signal sequence is given as:

\[y_b = \sum_{\ell =L_\text{min}}^{L_\text{max}} \bar{h}_\ell x_{b-\ell} + w_b, \quad b \in[L_\text{min}, N_B+L_\text{max}-1]\]

where \(\bar{h}_\ell\) are the discrete-time channel taps, \(x_{b}\) is the transmitted signal, and \(w_\ell\) Gaussian noise.

Starting from the first symbol, the demodulator cuts the input sequence into pieces of size cyclic_prefix_length + fft_size, and throws away any trailing symbols. For each piece, the cyclic prefix is removed and the fft_size-point discrete Fourier transform is computed. It is also possible that every OFDM symbol has a cyclic prefix of different length.

Since the input sequence starts at time \(L_\text{min}\), the FFT-window has a timing offset of \(L_\text{min}\) symbols, which leads to a subcarrier-dependent phase shift of \(e^{\frac{j2\pi k L_\text{min}}{N}}\), where \(k\) is the subcarrier index, \(N\) is the FFT size, and \(L_\text{min} \le 0\) is the largest negative time lag of the discrete-time channel impulse response. This phase shift is removed in this layer, by explicitly multiplying each subcarrier by \(e^{\frac{-j2\pi k L_\text{min}}{N}}\). This is a very important step to enable channel estimation with sparse pilot patterns that needs to interpolate the channel frequency response across subcarriers. It also ensures that the channel frequency response seen by the time-domain channel is close to the OFDMChannel.

Parameters:
  • fft_size (int) – FFT size (i.e., the number of subcarriers).

  • l_min (int) – The largest negative time lag of the discrete-time channel impulse response. It should be the same value as that used by the cir_to_time_channel function.

  • cyclic_prefix_length (int | numpy.ndarray | torch.Tensor) – Integer or vector of integers indicating the length of the cyclic prefix that is prepended to each OFDM symbol. None of its elements can be larger than the FFT size. Defaults to 0.

  • precision (Literal['single', 'double'] | None) – Precision used for internal calculations and outputs. If set to None, precision is used.

  • device (str | None) – Device for tensor operations. If None, device is used.

Inputs:

inputs – […, num_ofdm_symbols*(fft_size+cyclic_prefix_length)+n] or […, num_ofdm_symbols*fft_size+sum(cyclic_prefix_length)+n], torch.complex. Tensor containing the time-domain signal along the last dimension. n is a nonnegative integer.

Outputs:

x – […, num_ofdm_symbols, fft_size], torch.complex. Tensor containing the OFDM resource grid along the last two dimensions.

Examples

import torch
from sionna.phy.ofdm import OFDMModulator, OFDMDemodulator

modulator = OFDMModulator(cyclic_prefix_length=16)
demodulator = OFDMDemodulator(fft_size=72, l_min=0, cyclic_prefix_length=16)

x_freq = torch.randn(64, 14, 72, dtype=torch.complex64)
x_time = modulator(x_freq)
x_hat = demodulator(x_time)
print(torch.allclose(x_freq, x_hat, atol=1e-5))
# True

Attributes

property fft_size: int#

FFT size (number of subcarriers)

property l_min: int#

Largest negative time lag of the discrete-time channel

property cyclic_prefix_length: torch.Tensor#

Cyclic prefix length (scalar or per-symbol)

Methods

build(input_shape: tuple) None[source]#

Build the demodulator based on input shape.

Parameters:

input_shape (tuple)