view tempo_estimator.py @ 12:9973b7cd0d31 tip

Implement rest of tempo estimator
author Chris Cannam
date Mon, 08 Oct 2012 15:46:54 +0100
parents cb43d088e369
children
line wrap: on
line source

import audiofile as af
import numpy as np
import framer as fr
import signal_processing as sp

def detection_function(samples, hop):
    """Given some samples and a hop size, return a function corresponding to the interest level of the samples at intervals of the hop size."""
    n_frames = fr.get_frame_count(len(samples), hop)
    df = np.zeros(n_frames)
    for n in range(0, n_frames):
        frame = fr.get_frame(samples, hop, n)
        value = sp.rms(frame)
        df[n] = value
    return df

def find_tempo_from_autocorrelation(acf, bpm_min, bpm_max, hops_per_sec):
    lag_min = sp.bpm_to_lag(bpm_max, hops_per_sec)
    lag_max = sp.bpm_to_lag(bpm_min, hops_per_sec)
    acf_subset = acf[lag_min:lag_max]
    peakidx = np.argmax(acf_subset)
    lag_peak = lag_min + peakidx
    return sp.lag_to_bpm(lag_peak, hops_per_sec)

def estimate_tempo_of_samples(samples, samplerate):
    """Given some audio samples and their samplerate, return their estimated tempo in bpm."""
    hop = 512
    df = detection_function(samples, hop)
    acf = sp.autocorrelation(df)
    bpm_min = 70.0
    bpm_max = 150.0
    hops_per_sec = samplerate / float(hop)
    tempo = find_tempo_from_autocorrelation(acf, bpm_min, bpm_max, hops_per_sec)
    return tempo

def estimate_tempo_of_file(filename):
    """Given the name of a WAV file, return the estimated tempo in bpm."""
    (samples, samplerate) = af.read_all_mono_samples_from_file(filename)
    return estimate_tempo_of_samples(samples, samplerate)