sdr.rms_integration_time(x: ArrayLike, sample_rate: float = 1.0) float

Measures the RMS integration time \(T_{\text{rms}}\) of the signal \(x[n]\).

Parameters:
x: ArrayLike

The time-domain signal \(x[n]\) to measure.

Note

For best measurement performance, the time-domain signal should be very oversampled. This allows for better time precision.

sample_rate: float = 1.0

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

Returns:

The RMS integration time \(T_{\text{rms}}\) in seconds.

Notes

The root-mean-square (RMS) integration time \(T_{\text{rms}}\) is calculated by

\[ T_{\text{rms}} = \sqrt{\frac {\int_{-\infty}^{\infty} (t - \mu_t)^2 \cdot \left| x(t - \mu_t) \right|^2 \, dt} {\int_{-\infty}^{\infty} \left| x(t - \mu_t) \right|^2 \, dt} } \]

where \(x(t)\) is the continuous-time signal that was discretely sampled as \(x[n]\). The RMS integration time is measured about the centroid of the signal

\[ \mu_t = \frac {\int_{-\infty}^{\infty} t \cdot \left| x(t) \right|^2 \, dt} {\int_{-\infty}^{\infty} \left| x(t) \right|^2 \, dt} . \]

The RMS integration time is a measure of the energy spread of the signal about the centroid. For a rectangular signal, the RMS integration time is \(T_{\text{rms}} = T / \sqrt{12}\).

Examples

Calculate the RMS integration time of a signal with a rectangular envelope and duration of 1 second.

In [1]: symbol_rate = 100  # symbols/s

In [2]: sps = 100  # samples/symbol

In [3]: sample_rate = symbol_rate * sps  # samples/s

In [4]: n_symbols = symbol_rate  # Make a 1-second long signal

In [5]: t_s = n_symbols / symbol_rate  # Integration time (s)

In [6]: t_s / np.sqrt(12)
Out[6]: np.float64(0.2886751345948129)

Create a BPSK signal with a rectangular pulse shape. Measure the RMS integration time of the signal and compare it to the ideal rectangular envelope.

In [7]: psk = sdr.PSK(2, pulse_shape="rect", sps=sps)

In [8]: symbols = np.random.randint(0, psk.order, n_symbols)

In [9]: x_rect = psk.modulate(symbols).real

In [10]: sdr.rms_integration_time(x_rect, sample_rate=sample_rate)
Out[10]: np.float64(0.28864626708135344)

In [11]: plt.figure(); \
   ....: sdr.plot.time_domain(x_rect, sample_rate=sample_rate, label="Rectangular");
   ....: 
../../_images/sdr_rms_integration_time_1.png

Make the same measurements with square-root raised cosine (SRRC) pulse shaping.

In [12]: psk = sdr.PSK(2, pulse_shape="srrc", sps=sps)

In [13]: symbols = np.random.randint(0, psk.order, n_symbols)

In [14]: x_srrc = psk.modulate(symbols).real

In [15]: sdr.rms_integration_time(x_srrc, sample_rate=sample_rate)
Out[15]: np.float64(0.28865329576550935)

In [16]: plt.figure(); \
   ....: sdr.plot.time_domain(x_srrc, sample_rate=sample_rate, label="SRRC");
   ....: 
../../_images/sdr_rms_integration_time_2.png

For a given transmit energy, the RMS integration time is improved by increasing the energy at the edges of the signal. This can be achieved by applying a parabolic envelope to the BPSK signal. The energy of the signals is normalized. Notice the RMS integration time increases by 50% for the same transmit energy and duration.

In [17]: x_srrc_env = x_srrc * np.linspace(-1, 1, len(x_srrc))**2

In [18]: x_srrc_env *= np.sqrt(sdr.energy(x_srrc) / sdr.energy(x_srrc_env))

In [19]: sdr.rms_integration_time(x_srrc_env, sample_rate=sample_rate)
Out[19]: np.float64(0.4219690131724645)

In [20]: plt.figure(); \
   ....: sdr.plot.time_domain(x_srrc, sample_rate=sample_rate, label="SRRC"); \
   ....: sdr.plot.time_domain(x_srrc_env, sample_rate=sample_rate, label="SRRC + Parabolic Envelope");
   ....: 
../../_images/sdr_rms_integration_time_3.png