Why harmonic components appear only after a certain level when a signal is clipped?

I recently observed this phenomenon that when a signal is clipped the harmonics start to appear only after a certain level.

The Python code to reproduce the effect is given below. The signal has 3 components at 30, 60 and 90 Hz. So a maximum possible peak to peak voltage will be 3. I clipped the signal at various levels and observed the magnitude spectrum but the harmonics start to visibly noticable only if the clipping goes below -2.5 and 2.5.

Is this a well-known phenomenon? What is the possible explanation behind this?.

import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
from scipy.io import wavfile

labelsize   =   12
width       =   3.5
height      =   width / 1.618
lwidth      =   0.9

plt.rc('font', family='serif')
plt.rc('text', usetex=True)
plt.rc('xtick', labelsize=labelsize)
plt.rc('ytick', labelsize=labelsize)
plt.rc('axes', labelsize=labelsize)

def MagnitudeSpectrum(data, Fs, clip):
P = 20*np.log10(np.abs(np.fft.rfft(data)))
f = np.linspace(0, Fs/2, len(P))

fig, ax = plt.subplots()

plt.plot(f, P, color='k', ls='solid', linewidth=lwidth, label='')
plt.xlim(0, 500)
plt.title('Signal Clipped BW '+str(-1*clip)+' and'+str(clip))
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude [dB]')
# plt.show()
fig.set_size_inches(width, height)
fig.savefig('SignalMagSpectro_'+str(clip)+'.png', dpi = 600)

cliplevels = np.arange(2.2, 3.2, 0.1)

for clip in cliplevels:
Fs = 44100.0
t = np.arange(0, 10, 1/Fs)
data = np.sin(2*np.pi*30*t)+np.sin(2*np.pi*60*t)+ np.sin(2*np.pi*90*t) +0.1*np.random.randn(len(t))
data = np.clip(data, -1*clip, clip)
MagnitudeSpectrum(data, Fs, clip)

• have you drawn and compared the two time-domain waveforms? – robert bristow-johnson Mar 27 '18 at 7:23
• yep, as @robertbristow-johnson indicates, the phenomenom is best understood when you look at the time-domain waveform plot. If you want to give it a name, it's increasing nonlinearity of your system, necessarily leading to introduction of spurs/intermodulation products, and you can predict that by approximating your clipping transfer function with a power series. – Marcus Müller Mar 27 '18 at 10:25