import numpy, scipy, matplotlib.pyplot as plt, pandas, librosa, mir_eval
import IPython.display
from IPython.html.widgets import interact
plt.rcParams['figure.figsize'] = (14,5)
:0: FutureWarning: IPython widgets are experimental and may change in the future.
librosa.beat.beat_track
¶Download an audio file:
import urllib
urllib.urlretrieve('http://audio.musicinformationretrieval.com/1_bar_funk_groove.mp3',
filename='1_bar_funk_groove.mp3')
('1_bar_funk_groove.mp3', <httplib.HTTPMessage instance at 0x10f3d96c8>)
Read the file:
x, fs = librosa.load('1_bar_funk_groove.mp3')
print fs
IPython.display.Audio(x, rate=fs)
22050
Use librosa.beat.beat_track
to estimate the beat locations and the global tempo:
tempo, beat_frames = librosa.beat.beat_track(x, fs, start_bpm=60)
print tempo
print beat_frames
56.1735733696 [ 47 92 138 184 231 275 321 366 412 459 504 550 595 641]
Plot the beat locations over the waveform:
def plot_beats(beat_frames):
plt.figure()
plt.plot(x, alpha=0.5)
beat_samples = librosa.frames_to_samples(beat_frames)
plt.vlines(beat_samples, -1, 1, color='r')
plot_beats(beat_frames)
Plot a histogram of the intervals between adjacent beats:
def plot_beat_histogram(beat_frames):
beat_times = librosa.frames_to_time(beat_frames)
beat_times_diff = numpy.diff(beat_times)
plt.figure()
plt.hist(beat_times_diff, bins=50, range=(0,4))
plt.xlabel('Beat Length (seconds)')
plt.ylabel('Count')
plot_beat_histogram(beat_frames)
Visually, it's difficult to tell how correct the estimated beats are. Let's listen to a click track:
def sonify_beats(beat_frames):
beat_times = librosa.frames_to_time(beat_frames)
clicks = mir_eval.sonify.clicks(beat_times, fs, length=len(x))
return IPython.display.Audio(x + clicks, rate=fs)
sonify_beats(beat_frames)
@interact(start_bpm=(30, 180, 20), tightness_exp=(-1, 4, 0.5))
def interact_f(start_bpm=60, tightness_exp=2):
tempo, beat_frames = librosa.beat.beat_track(x, fs, start_bpm=start_bpm, tightness=10**tightness_exp)
plot_beats(beat_frames)
plot_beat_histogram(beat_frames)
IPython.display.display(sonify_beats(beat_frames))