sdr.raised_cosine(alpha: float, span: int, sps: int, norm: 'power' | 'energy' | 'passband' = 'energy') NDArray[float64]

Returns a raised cosine (RC) pulse shape.

Parameters:
alpha: float

The excess bandwidth \(0 \le \alpha \le 1\) of the filter.

span: int

The length of the filter in symbols. The length of the filter is span * sps + 1 samples. The filter order span * sps must be even.

sps: int

The number of samples per symbol.

norm: 'power' | 'energy' | 'passband' = 'energy'

Indicates how to normalize the pulse shape.

  • "power": The pulse shape is normalized so that the maximum power is 1.

  • "energy": The pulse shape is normalized so that the total energy is 1.

  • "passband": The pulse shape is normalized so that the passband gain is 1.

Returns:

The raised cosine pulse shape.

Notes

The raised cosine pulse shape has a transfer function of

\[\begin{split} H(f) = \begin{cases} T_{sym}, & \displaystyle 0 \le \left| f \right| \le \frac{1 - \alpha}{2 T_{sym}} \\ \displaystyle \frac{T_{sym}}{2} \left[1 + \cos\left(\frac{\pi T_{sym}}{\alpha}\left(\left| f \right| - \frac{1 - \alpha}{2 T_{sym}}\right)\right)\right], & \displaystyle \frac{1 - \alpha}{2 T_{sym}} \le \left| f \right| \le \frac{1 + \alpha}{2 T_{sym}} \\ 0, & \displaystyle \left| f \right| \ge \frac{1 + \alpha}{2 T_{sym}} \end{cases} \end{split}\]

The impulse response is defined as

\[ h(t) = \frac {\displaystyle \sin\left(\frac{\pi t}{T_{sym}}\right) \cos\left(\frac{\pi \alpha t}{T_{sym}}\right)} {\displaystyle \frac{\pi t}{T_{sym}} \left[1 - \left(\frac{2 \alpha t}{T_{sym}} \right)^2 \right]} \]

References

  • Michael Rice, Digital Communications: A Discrete Time Approach, Appendix A.

Examples

The excess bandwidth \(\alpha\) controls bandwidth of the filter. A smaller \(\alpha\) results in a narrower bandwidth at the expense of higher sidelobes.

In [1]: h_0p1 = sdr.raised_cosine(0.1, 8, 10); \
   ...: h_0p5 = sdr.raised_cosine(0.5, 8, 10); \
   ...: h_0p9 = sdr.raised_cosine(0.9, 8, 10)
   ...: 

In [2]: plt.figure(); \
   ...: sdr.plot.impulse_response(h_0p1, label=r"$\alpha = 0.1$"); \
   ...: sdr.plot.impulse_response(h_0p5, label=r"$\alpha = 0.5$"); \
   ...: sdr.plot.impulse_response(h_0p9, label=r"$\alpha = 0.9$")
   ...: 

In [3]: plt.figure(); \
   ...: sdr.plot.magnitude_response(h_0p1, label=r"$\alpha = 0.1$"); \
   ...: sdr.plot.magnitude_response(h_0p5, label=r"$\alpha = 0.5$"); \
   ...: sdr.plot.magnitude_response(h_0p9, label=r"$\alpha = 0.9$")
   ...: 
../../_images/sdr_raised_cosine_1.png ../../_images/sdr_raised_cosine_2.png

The span of the filter affects the stopband attenuation. A longer span results in greater stopband attenuation and lower sidelobes.

In [4]: h_4 = sdr.raised_cosine(0.1, 4, 10); \
   ...: h_8 = sdr.raised_cosine(0.1, 8, 10); \
   ...: h_16 = sdr.raised_cosine(0.1, 16, 10)
   ...: 

In [5]: plt.figure(); \
   ...: sdr.plot.impulse_response(h_4, label="span = 4"); \
   ...: sdr.plot.impulse_response(h_8, label="span = 8"); \
   ...: sdr.plot.impulse_response(h_16, label="span = 16")
   ...: 

In [6]: plt.figure(); \
   ...: sdr.plot.magnitude_response(h_4, label="span = 4"); \
   ...: sdr.plot.magnitude_response(h_8, label="span = 8"); \
   ...: sdr.plot.magnitude_response(h_16, label="span = 16")
   ...: 
../../_images/sdr_raised_cosine_3.png ../../_images/sdr_raised_cosine_4.png

See the Pulse shapes example.