import matplotlib
if not hasattr(matplotlib.RcParams, "_get"):
matplotlib.RcParams._get = dict.get
1.4 Clipping#
One last practical concern. The DAC has to take the \([-1, 1]\) amplitude values and scale them back to \([-p_{\text{max}}, p_{\text{max}}]\). Accordingly, when you hand it samples whose absolute values exceed \(1\), it will simply clip them to avoid exceeding \(|p_{\text{max}}\)|:
Warning
A critical safety note. When experimenting with synthesis code, do not wear headphones until you know the output is bounded. It is very easy to write a one-line bug that produces a much louder sound than you intended, and a sudden loud signal directly against your eardrums can cause real damage. Listen through external speakers at low volume while you debug, then cautiously put headphones on once the output is well-behaved.
Clipping is extremely intrusive: it introduces a harsh, raspy character into the sound, and at high amplitudes can damage speakers as well as ears. For example, multiplying a clean 440 Hz sine wave by 2 saturates the DAC and produces a signal that’s close to a square wave. Compare them directly:
The interactive below drives the same sine into the clipper. Drag the gain past 1 and watch the tops flatten.
Drag the gain: the faint curve is the scaled sine headed for the DAC, and the red curve is what survives the clipper. The audio card underneath plays the result, attenuated for safe playback.
A simple defensive habit while developing synthesis code is to normalize your output to lie within \([-1, 1]\) before sending it to the DAC, e.g.,