Zero Crossing Rate

Contents

Zero Crossing Rate#

import IPython.display as ipd
import matplotlib.pyplot as plt
import librosa.display

from mirdotcom import mirdotcom

mirdotcom.init()

The zero crossing rate indicates the number of times that a signal crosses the horizontal axis.

Let’s load a signal:

filename = mirdotcom.get_audio("simple_loop.wav")
x, sr = librosa.load(filename)

Listen to the signal:

ipd.Audio(x, rate=sr)

Plot the signal:

plt.figure(figsize=(14, 5))
librosa.display.waveshow(x, sr=sr)
plt.ylabel("Amplitude")
Text(117.47222222222221, 0.5, 'Amplitude')
../../_images/3f35a0928da6ce8509d317a8fadc938da1a55c870b166d5580ab2a8581ef8cdd.png

Let’s zoom in:

n0 = 6500
n1 = 7500
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.ylabel("Amplitude")
Text(0, 0.5, 'Amplitude')
../../_images/303dc4bf9f0494bcce70258538d69a8a598f8535cb851da86acdcd3d6c1b7989.png

I count five zero crossings. Let’s compute the zero crossings using librosa.

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
zero_crossings.shape
(1000,)

That computed a binary mask where True indicates the presence of a zero crossing. To find the total number of zero crossings, use sum:

print(sum(zero_crossings))
5

To find the zero-crossing rate over time, use zero_crossing_rate:

zcrs = librosa.feature.zero_crossing_rate(x)
print(zcrs.shape)
(1, 97)

Plot the zero-crossing rate:

plt.figure(figsize=(14, 5))
plt.plot(zcrs[0])
plt.ylabel("Zero crossing rate")
Text(0, 0.5, 'Zero crossing rate')
../../_images/1e48f18021e244333da25d4a14782f686f88d3c07e8bbdca3ddd7d15e0807f3c.png

Note how the high zero-crossing rate corresponds to the presence of the snare drum.

The reason for the high rate near the beginning is because the silence oscillates quietly around zero:

plt.figure(figsize=(14, 5))
plt.plot(x[:1000])
plt.ylim(-0.0001, 0.0001)
plt.ylabel("Amplitude")
Text(0, 0.5, 'Amplitude')
../../_images/e1f0d418dd04e92c7948544f3d882053b6c6c40b699f2a3ebb5ab2be6564b64c.png

A simple hack around this is to add a small constant before computing the zero crossing rate:

zcrs = librosa.feature.zero_crossing_rate(x + 0.0001)
plt.figure(figsize=(14, 5))
plt.plot(zcrs[0])
plt.ylabel("Zero crossing rate")
Text(0, 0.5, 'Zero crossing rate')
../../_images/9d34d9960e9e68ea718dee49c25b91162e534a4dc07121b364d222963f9f3df5.png

Questions#

Try for other audio files. Does the zero-crossing rate still return something useful in polyphonic mixtures?

mirdotcom.list_audio()
simple_piano.wav
latin_groove.mp3
clarinet_c6.wav
cowbell.wav
classic_rock_beat.mp3
oboe_c6.wav
sir_duke_trumpet_fast.mp3
sir_duke_trumpet_slow.mp3
jangle_pop.mp3
125_bounce.wav
brahms_hungarian_dance_5.mp3
58bpm.wav
conga_groove.wav
funk_groove.mp3
tone_440.wav
sir_duke_piano_fast.mp3
thx_original.mp3
simple_loop.wav
classic_rock_beat.wav
c_strum.wav
prelude_cmaj.wav
sir_duke_piano_slow.mp3
busta_rhymes_hits_for_days.mp3