In [1]:
%matplotlib inline
import seaborn
import numpy, scipy, matplotlib.pyplot as plt, IPython.display as ipd
import librosa, librosa.display
from ipywidgets import interact
plt.rcParams['figure.figsize'] = (14, 5)

Beat Tracking¶

librosa.beat.beat_track¶

Load an audio file:

In [2]:
x, sr = librosa.load('audio/58bpm.wav')
ipd.Audio(x, rate=sr)
Out[2]:

Use librosa.beat.beat_track to estimate the beat locations and the global tempo:

In [3]:
tempo, beat_times = librosa.beat.beat_track(x, sr=sr, start_bpm=60, units='time')
print tempo
print beat_times
58.7269176136
[ 1.06811791  2.11301587  3.11147392  4.17959184  5.20126984  6.2461678
  7.2678458 ]

Plot the beat locations over the waveform:

In [4]:
librosa.display.waveplot(x, alpha=0.6)
plt.vlines(beat_times, -1, 1, color='r')
plt.ylim(-1, 1)
Out[4]:
(-1, 1)

Plot a histogram of the intervals between adjacent beats:

In [5]:
beat_times_diff = numpy.diff(beat_times)
plt.hist(beat_times_diff, bins=50, range=(0,4))
plt.xlabel('Beat Length (seconds)')
plt.ylabel('Count')
Out[5]:
<matplotlib.text.Text at 0x1116df1d0>

Visually, it's difficult to tell how correct the estimated beats are. Let's listen to a click track:

In [6]:
clicks = librosa.clicks(beat_times, sr=sr, length=len(x))
ipd.Audio(x + clicks, rate=sr)
Out[6]:

Use the IPython interactive widgets to observe how the output changes as we vary the parameters of the beat tracker.

In [7]:
def f(start_bpm, tightness_exp):
    return librosa.beat.beat_track(x, sr=sr, start_bpm=start_bpm, tightness=10**tightness_exp, units='time')
interact(f, start_bpm=60, tightness_exp=2)
Out[7]:
<function __main__.f>

Questions¶

Try other audio files:

In [8]:
ls audio
125_bounce.wav         conga_groove.wav       prelude_cmaj.wav
58bpm.wav              funk_groove.mp3        simple_loop.wav
c_strum.wav            jangle_pop.mp3         simple_piano.wav
clarinet_c6.wav        latin_groove.mp3       tone_440.wav
classic_rock_beat.wav  oboe_c6.wav