sdr.frequency_offset(x: NDArray, freq: ArrayLike, freq_rate: ArrayLike = 0, phase: ArrayLike = 0, sample_rate: float = 1) NDArray

Applies a frequency and phase offset to the time-domain signal \(x[n]\).

Parameters:
x: NDArray

The time-domain signal \(x[n]\) to which the frequency offset is applied.

freq: ArrayLike

The frequency offset \(f\) in Hz (or in cycles/sample if sample_rate=1).

freq_rate: ArrayLike = 0

The frequency offset rate \(f_{\text{rate}}\) in Hz/s (or in cycles/sample^2 if sample_rate=1).

phase: ArrayLike = 0

The phase offset \(\phi\) in degrees.

sample_rate: float = 1

The sample rate \(f_s\) in samples/s.

Returns:

The signal \(x[n]\) with frequency offset applied.

Examples

Create a QPSK reference signal.

In [1]: psk = sdr.PSK(4, phase_offset=45); \
   ...: s = np.random.randint(0, psk.order, 1_000); \
   ...: x = psk.modulate(s)
   ...: 

Add a frequency offset of 1 cycle per 10,000 symbols.

In [2]: freq = 1e-4; \
   ...: y = sdr.frequency_offset(x, freq)
   ...: 

In [3]: plt.figure(figsize=(10, 5)); \
   ...: sdr.plot.constellation(x, label="$x[n]$", zorder=2); \
   ...: sdr.plot.constellation(y, label="$y[n]$", zorder=1); \
   ...: plt.title(f"{freq} cycles/sample frequency offset"); \
   ...: plt.tight_layout()
   ...: 
../../_images/sdr_frequency_offset_1.png

Add a frequency offset of -1 cycle per 20,000 symbols and a phase offset of -45 degrees.

In [4]: freq = -5e-5; \
   ...: phase = -45; \
   ...: y = sdr.frequency_offset(x, freq, phase=phase)
   ...: 

In [5]: plt.figure(figsize=(10, 5)); \
   ...: sdr.plot.constellation(x, label="$x[n]$", zorder=2); \
   ...: sdr.plot.constellation(y, label="$y[n]$", zorder=1); \
   ...: plt.title(f"{freq} cycles/sample frequency and {phase} deg offset"); \
   ...: plt.tight_layout()
   ...: 
../../_images/sdr_frequency_offset_2.png