Source code for sionna.ofdm.modulator

#
# SPDX-FileCopyrightText: Copyright (c) 2021-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
"""Class definition for the OFDM Modulator"""

import tensorflow as tf
from tensorflow.keras.layers import Layer
from tensorflow.signal import ifftshift
from sionna.utils import flatten_last_dims
from sionna.signal import ifft


[docs]class OFDMModulator(Layer): """ OFDMModulator(cyclic_prefix_length, **kwargs) Computes the time-domain representation of an OFDM resource grid with (optional) cyclic prefix. Parameters ---------- cyclic_prefix_length : int Integer indicating the length of the cyclic prefix that it prepended to each OFDM symbol. It cannot be longer than the FFT size. Input ----- : [...,num_ofdm_symbols,fft_size], tf.complex A resource grid in the frequency domain. Output ------ : [...,num_ofdm_symbols*(fft_size+cyclic_prefix_length)], tf.complex Time-domain OFDM signal. """ def __init__(self, cyclic_prefix_length=0, **kwargs): super().__init__(**kwargs) self.cyclic_prefix_length = cyclic_prefix_length @property def cyclic_prefix_length(self): return self._cyclic_prefix_length @cyclic_prefix_length.setter def cyclic_prefix_length(self, value): assert value >=0, "`cyclic_prefix_length` must be nonnegative." self._cyclic_prefix_length = value def build(self, input_shape): # Verify that cyclic prefix is not longer than the FFT size. fft_size = input_shape[-1] assert self.cyclic_prefix_length<=fft_size, \ "shape(inputs)[-1] must not be smaller than `cylic_prefix_length`" def call(self, inputs): # Shift DC subcarrier to first position inputs = ifftshift(inputs, axes=-1) # Compute IFFT along the last dimension x = ifft(inputs) # Obtain cyclic prefix cp = x[...,tf.shape(inputs)[-1]-self._cyclic_prefix_length:] # Prepend cyclic prefix x = tf.concat([cp, x], -1) # Serialize last two dimensions x = flatten_last_dims(x, 2) return x