In [1]:
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)
Download an audio file:
In [2]:
import urllib
urllib.urlretrieve('http://audio.musicinformationretrieval.com/1_bar_funk_groove.mp3',
filename='1_bar_funk_groove.mp3')
Out[2]:
Read the file:
In [3]:
x, fs = librosa.load('1_bar_funk_groove.mp3')
print fs
IPython.display.Audio(x, rate=fs)
Out[3]:
Use librosa.beat.beat_track
to estimate the beat locations and the global tempo:
In [4]:
tempo, beat_frames = librosa.beat.beat_track(x, fs, start_bpm=60)
print tempo
print beat_frames
Plot the beat locations over the waveform:
In [5]:
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:
In [6]:
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:
In [7]:
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)
Out[7]:
Use the IPython interactive widgets to observe how the output changes as we vary the parameters of the beat tracker. (The interactive widget is only visible in the editable IPython notebook, not the read-only version.)
In [8]:
@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))