# Use Custom OFDM Sample Rate and Custom FFT Size

This example explains how to set custom values for the sample rate input, `SampleRate`, and the fast Fourier transform (FFT) size input, `Nfft`, when you call an OFDM function (`nrOFDMModulate`, `nrOFDMInfo`, and `nrOFDMDemodulate`).

### Custom OFDM Sample Rate

The value that you set for the `SampleRate` input determines the sample rate of the waveform.

The nominal sample rate corresponding to the FFT size used in the OFDM modulation, ${\mathit{FFT}}_{\mathit{SR}}$, is equal to `Nfft * carrier.SubcarrierSpacing * 1000`, where `carrier` is the input argument of the function call, specifying the carrier configuration.

Because the resampling of the OFDM-modulated waveform is by a factor of `SampleRate/`${\mathit{FFT}}_{\mathit{SR}}$, the resampling is costly if `SampleRate` and ${\mathit{FFT}}_{\mathit{SR}}$ do not have large common factors.

### Custom FFT Size

The value that you set for the `Nfft` input must satisfy these conditions.

• `Nfft` is an integer value resulting in integer-valued cyclic prefix lengths.

• `Nfft` is an integer power of 2.

• `Nfft` results in a maximum occupancy of 100%. The actual occupancy is equal to `carrier.NSizeGrid * 12 / Nfft`.

You can only achieve a bandwidth occupancy of exactly 100% when these conditions apply.

• The FFT and the carrier grid have the same size, that is, `Nfft = carrier.NSizeGrid * 12`.

• Resampling is not needed, that is, `SampleRate = Nfft * carrier.SubcarrierSpacing * 1000`.

### Plot Bandwidth Occupancy

Create a carrier configuration object.

`carrier = nrCarrierConfig;`

Set the `SampleRate` for each `NSizeGrid` such that the bandwidth occupancy (`txBW / SampleRate`) is 90%. Set `Nfft` to a power of 2.

```nSizeGrids = 1:275; userSampleRateUserNfft = zeros(1,275); fftOccupancy = zeros(1,275); for nSizeGrid = 1:275 carrier.NSizeGrid = nSizeGrid; % Transmission bandwidth of OFDM waveform txBW = carrier.NSizeGrid * 12 * carrier.SubcarrierSpacing * 1000; sr = txBW / 0.9; nfft = max(128,2^ceil(log2(carrier.NSizeGrid * 12))); ofdmInfo = nrOFDMInfo(carrier,'SampleRate',sr,'Nfft',nfft); userSampleRateUserNfft(nSizeGrid) = ofdmInfo.Nfft; fftOccupancy(nSizeGrid) = carrier.NSizeGrid * 12 / ofdmInfo.Nfft; end```

Plot the resulting FFT size.

```figure; plot(nSizeGrids,userSampleRateUserNfft,'x'); title({'Nfft Selected with Power of 2 Size' 'with Bandwidth Occupancy of 90%'}); axis([1 275 min(userSampleRateUserNfft) max(userSampleRateUserNfft)]); xlabel('NSizeGrid'); xticks([1 52 106 160 216 275]); ylabel('Nfft'); yticks(2.^(7:12));```

Plot the resulting FFT occupancy.

```figure; plot(nSizeGrids,fftOccupancy,'x'); title({'FFT Occupancy' 'with Bandwidth Occupancy of 90%'}); axis([1 275 0 1]); xlabel('NSizeGrid'); xticks([1 52 106 160 216 275]); ylabel('FFT Occupancy');```

### Get OFDM Information

Update the carrier to 25 resource blocks (RBs).

`carrier.NSizeGrid = 25;`

Get OFDM information.

`ofdmInfo = nrOFDMInfo(carrier)`
```ofdmInfo = struct with fields: Nfft: 512 SampleRate: 7680000 CyclicPrefixLengths: [40 36 36 36 36 36 36 40 36 36 36 36 36 36] SymbolLengths: [552 548 548 548 548 548 548 552 548 548 548 ... ] Windowing: 18 SymbolPhases: [0 0 0 0 0 0 0 0 0 0 0 0 0 0] SymbolsPerSlot: 14 SlotsPerSubframe: 1 SlotsPerFrame: 10 ```

The `CyclicPrefixLengths` and `SymbolLengths` fields in the output structure return the cyclic prefix lengths and total OFDM symbol lengths for each OFDM symbol in a subframe. The total OFDM symbol length is composed of the cyclic prefix and the nominal OFDM symbol length equal to the FFT size.

`ofdmInfo.SymbolLengths - ofdmInfo.CyclicPrefixLengths`
```ans = 1×14 512 512 512 512 512 512 512 512 512 512 512 512 512 512 ```

Because OFDM symbol construction is performed using an IFFT of size that you specify in the `Nfft` input, the `CyclicPrefixLengths` and `SymbolLengths` fields return values in terms of this `Nfft` value. The specified `Nfft` is also returned in the `Nfft` field of the output.

```nfft = 640; ofdmInfo = nrOFDMInfo(carrier,'Nfft',nfft)```
```ofdmInfo = struct with fields: Nfft: 640 SampleRate: 9600000 CyclicPrefixLengths: [50 45 45 45 45 45 45 50 45 45 45 45 45 45] SymbolLengths: [690 685 685 685 685 685 685 690 685 685 685 ... ] Windowing: 22 SymbolPhases: [0 0 0 0 0 0 0 0 0 0 0 0 0 0] SymbolsPerSlot: 14 SlotsPerSubframe: 1 SlotsPerFrame: 10 ```
`ofdmInfo.SymbolLengths - ofdmInfo.CyclicPrefixLengths`
```ans = 1×14 640 640 640 640 640 640 640 640 640 640 640 640 640 640 ```

For the default sample rate, the number of time-domain samples of each OFDM symbol matches the values of `SymbolLengths` field. If you specify the `SampleRate` input, the specified value is returned in the `SampleRate` field of the output. However, the `CyclicPrefixLengths` and `SymbolLengths` fields are expressed in terms of the IFFT size used during OFDM symbol construction, therefore, these values do not change in the output. The waveform is resampled to the sample rate that you specify after OFDM symbol construction. Depending on the sample rate, the length of the cyclic prefixes and nominal OFDM symbols in the corresponding OFDM waveform may not be an integer number of samples.

```sr = 1.35 * nfft * carrier.SubcarrierSpacing * 1e3; ofdmInfo = nrOFDMInfo(carrier,'Nfft',640,'SampleRate',sr)```
```ofdmInfo = struct with fields: Nfft: 640 SampleRate: 12960000 CyclicPrefixLengths: [50 45 45 45 45 45 45 50 45 45 45 45 45 45] SymbolLengths: [690 685 685 685 685 685 685 690 685 685 685 ... ] Windowing: 22 SymbolPhases: [0 0 0 0 0 0 0 0 0 0 0 0 0 0] SymbolsPerSlot: 14 SlotsPerSubframe: 1 SlotsPerFrame: 10 ```
`ratio = ofdmInfo.SampleRate / (ofdmInfo.Nfft * carrier.SubcarrierSpacing * 1e3)`
```ratio = 1.3500 ```
`disp(num2str(ofdmInfo.SymbolLengths*ratio,'%0.3f '));`
```931.500 924.750 924.750 924.750 924.750 924.750 924.750 931.500 924.750 924.750 924.750 924.750 924.750 924.750 ```