sdr.frequency_offset(x: ArrayLike, offset: ArrayLike, offset_rate: ArrayLike = 0.0, phase: ArrayLike = 0.0, sample_rate: float = 1.0) NDArray

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

Parameters:
x: ArrayLike

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

offset: ArrayLike

The frequency offset \(\Delta f_c = f_{c,\text{new}} - f_{c,\text{old}}\) in Hz.

offset_rate: ArrayLike = 0.0

The frequency offset rate \(\Delta f_c / \Delta t\) in Hz/s.

phase: ArrayLike = 0.0

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

sample_rate: float = 1.0

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

Returns:

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

Examples

Create a reference signal with a constant frequency of 1 cycle per 100 samples.

In [1]: x = np.exp(1j * 2 * np.pi / 100 * np.arange(100))

Add a frequency offset of 1 cycle per 100 samples (the length of the signal). Notice that the signal now rotates through 2 cycles instead of 1.

In [2]: freq = 1 / 100

In [3]: y = sdr.frequency_offset(x, freq)

In [4]: plt.figure(); \
   ...: sdr.plot.time_domain(np.unwrap(np.angle(x)) / (2 * np.pi), label="$x[n]$"); \
   ...: sdr.plot.time_domain(np.unwrap(np.angle(y)) / (2 * np.pi), label="$y[n]$"); \
   ...: plt.ylabel("Absolute phase (cycles)"); \
   ...: plt.title("Constant frequency offset (linear phase)");
   ...: 
../../_images/sdr_frequency_offset_1.png

Add a frequency rate of change of 2 cycles per 100^2 samples. Notice that the signal now rotates through 4 cycles instead of 2.

In [5]: freq_rate = 2 / 100**2

In [6]: y = sdr.frequency_offset(x, freq, freq_rate)

In [7]: plt.figure(); \
   ...: sdr.plot.time_domain(np.unwrap(np.angle(x)) / (2 * np.pi), label="$x[n]$"); \
   ...: sdr.plot.time_domain(np.unwrap(np.angle(y)) / (2 * np.pi), label="$y[n]$"); \
   ...: plt.ylabel("Absolute phase (cycles)"); \
   ...: plt.title("Linear frequency offset (quadratic phase)");
   ...: 
../../_images/sdr_frequency_offset_2.png