def get_last_beat(cumscore): """Get the last beat from the cumulative score array""" maxes = librosa.localmax(cumscore) med_score = np.median(cumscore[np.argwhere(maxes)]) # The last of these is the last beat (since score generally increases) return np.argwhere((cumscore * maxes * 2 > med_score)).max()
def onset_estimate_bpm(onsets, start_bpm, fft_res): """Estimate the BPM from an onset envelope Arguments: onsets -- (ndarray) time-series of onset strengths start_bpm -- (float) initial guess of the BPM fft_res -- (float) resolution of FFT (sample rate / hop length) Returns bpm: bpm -- (float) estimated BPM """ ac_size = 4.0 duration = 90.0 end_time = 90.0 bpm_std = 1.0 # Chop onsets to X[(upper_limit - duration):upper_limit] # or as much as will fit maxcol = min(len(onsets)-1, np.round(end_time * fft_res)) mincol = max(0, maxcol - np.round(duration * fft_res)) # Use auto-correlation out of 4 seconds (empirically set??) ac_window = np.round(ac_size * fft_res) # Compute the autocorrelation x_corr = librosa.autocorrelate(onsets[mincol:maxcol], ac_window) # FIXME: 2013-01-25 08:55:40 by Brian McFee <*****@*****.**> # this fails if ac_window > length of song # re-weight the autocorrelation by log-normal prior bpms = 60.0 * fft_res / (np.arange(1, ac_window+1)) # Smooth the autocorrelation by a log-normal distribution x_corr = x_corr * np.exp(-0.5 * ((np.log2(bpms / start_bpm)) / bpm_std)**2) # Get the local maximum of weighted correlation x_peaks = librosa.localmax(x_corr) # Zero out all peaks before the first negative x_peaks[:np.argmax(x_corr < 0)] = False # Choose the best peak out of .33, .5, 2, 3 * start_period candidates = np.multiply( np.argmax(x_peaks * x_corr), [1.0/3, 1.0/2, 1.0, 2.0, 3.0]) candidates = candidates.astype(int) candidates = candidates[candidates < ac_window] best_period = np.argmax(x_corr[candidates]) return 60.0 * fft_res / candidates[best_period]
def activation_upsample(A_low, sr): n, k, _, sr_old = A_low.shape A = np.zeros((n, k, 1, sr)) for i in range(n): for j in range(k): act_res = librosa.resample(A_low[i, j, :, :].squeeze(), orig_sr=sr_old, target_sr=sr) # Local-max filter act_res A[i, j, :, : min(sr, len(act_res))] = librosa.localmax(act_res) * act_res return A
def activation_upsample(A_low, sr): n, k, _, sr_old = A_low.shape A = np.zeros((n, k, 1, sr)) for i in range(n): for j in range(k): act_res = librosa.resample(A_low[i, j, :, :].squeeze(), orig_sr=sr_old, target_sr=sr) # Local-max filter act_res A[i, j, :, :min(sr, len(act_res) )] = librosa.localmax(act_res) * act_res return A
def __test_peaks(tempo, win_length, window, norm): # Generate an evenly-spaced pulse train odf = np.zeros(duration * sr // hop_length) spacing = sr * 60. // (hop_length * tempo) odf[::int(spacing)] = 1 tempogram = librosa.feature.tempogram(onset_envelope=odf, sr=sr, hop_length=hop_length, win_length=win_length, window=window, norm=norm) # Check the shape of the output eq_(tempogram.shape[0], win_length) eq_(tempogram.shape[1], len(odf)) # Mean over time to wash over the boundary padding effects idx = np.where(librosa.localmax(tempogram.max(axis=1)))[0] # Indices should all be non-zero integer multiples of spacing assert np.allclose(idx, spacing * np.arange(1, 1 + len(idx)))