sdr.sample_rate_offset(x: NDArray, ppm: float) NDArray

Applies a sample rate offset to the time-domain signal \(x[n]\).

Parameters:
x: NDArray

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

ppm: float

The sample rate offset \(f_{s,\text{new}} / f_s\) in parts per million (ppm).

Returns:

The signal \(x[n]\) with sample rate 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 10 ppm of sample rate offset.

In [2]: ppm = 10; \
   ...: y = sdr.sample_rate_offset(x, ppm)
   ...: 

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"{ppm} ppm sample rate offset"); \
   ...: plt.tight_layout()
   ...: 
../../_images/sdr_sample_rate_offset_1.png

Add 100 ppm of sample rate offset.

In [4]: ppm = 100; \
   ...: y = sdr.sample_rate_offset(x, ppm)
   ...: 

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"{ppm} ppm sample rate offset"); \
   ...: plt.tight_layout()
   ...: 
../../_images/sdr_sample_rate_offset_2.png