2
$\begingroup$

Objective: Finding the BPM of a short drum loop.

Approach:

% Step 1: Get audio signal and sample rate
[audio_signal, Fs] = audioread(".\90-bpm.wav"); % Drum loop recorded at 90bpm
audio_signal = audio_signal(:,1); % Only use 1 channel
short_signal = audio_signal(1:1e5,:); % Get short version of sample

% Step 2: Get the audio signal length
audio_length = length(audio_signal);

% Step 3: Create the time vector based on the audio signal length and sampling rate
time = (0:audio_length-1) / Fs; % Used for plotting time axis

% Step 4: Plot the audio signal
plot(time, audio_signal);
xlabel('Time (seconds)');
ylabel('Amplitude');
title('Audio Signal');
grid on;

% Use correlation with a shorter version of the signal
[result, lags] = xcorr(audio_signal, short_signal);

plot(lags/Fs, result); % Normalized lag-axis
xlabel('Lag');
ylabel('xcrorr result');
grid on;

% Find the peaks at their locations
[peaks, locs] = findpeaks(result);

Result enter image description here

Interpretation

The result shows two large peaks, where I assume the first one corresponds to the start of both samples (highest point of similarity at lag = 0) and the second largest peak where I assume both samples are most likely repeating itself.

Questions

I would like to understand how I can use this result to find the bpm of the drum loop. Would I have to find the time between each peak? How could I determine the bpm using the smaller peaks seen through the result? How does "lag/delay" translate to time?

Thank you in advance!

EDIT: Added plotting lines to show normalization of lag scale.

FOLLOW-UP

Based on @Jdip answer I have added the following code:

% Use correlation with a shorter version of the signal
[result, lags] = xcorr(audio_signal, short_signal);

plot(lags, result); % Normalized lag-axis
xlabel('Lag');
ylabel('xcrorr result');
grid on;

% Find the peaks at their locations
[pksort, locsort] = findpeaks(result, lags, "SortStr", "descend");
pkpairs= pksort(1:2,:);
locpairs = locsort(:, 1:2);

loc_time = locpairs(:,2)/Fs;
beat_sec = 1/loc_time;

Result

enter image description here

>> locpairs/Fs

ans =

         0    2.6667

>> loc_time = locpairs(:,2)/Fs;
>> loc_time

loc_time =

    2.6667

>> beat_sec = 1/loc_time;
>> beat_sec

beat_sec =

    0.3750

>> beat_sec * 60

ans =

   22.5000

Original Signal

enter image description here

$\endgroup$
0

1 Answer 1

2
$\begingroup$

$$\texttt{BPM} = \frac{60 \cdot f_s}{\texttt{lag}} $$

Assuming a sampling frequency $f_s=44100$, we’d expect the highest correlation peak to be at $\texttt{lag}\,29400$, which is more or less in agreement with your correlation plot (the x-axis is missing a $\times 10^5$ scaling factor).

$\endgroup$
9
  • $\begingroup$ The assumption is correct, the sampling frequency is 44.1kHz. Where does the 60 come from in the equation for the BPM? $\endgroup$ Aug 9 at 15:25
  • $\begingroup$ @ChalupaBatmac $f_s/\texttt{lag}$ has units of beats/second, and there are 60 seconds in 1 minute. So you multiply by 60 to get beats/minute $\endgroup$
    – Jdip
    Aug 9 at 16:54
  • 1
    $\begingroup$ To give you more detail. Your first correlation peak is at lag (approximately, I can’t see the actual lag) $29000$. So in terms of seconds, that’s $29000/44100 \approx 0.66$ seconds. So the beat repeats every $0.66$ seconds which means there are $1/0.66 = 1.51$ beats per second, or $1.51 \times 60 \approx 90$ beats per minute. Don’t forget to mark the answer if you’re satisfied. $\endgroup$
    – Jdip
    Aug 9 at 16:58
  • 1
    $\begingroup$ Can you post a plot of your signal please? $\endgroup$
    – Jdip
    Aug 10 at 16:45
  • 1
    $\begingroup$ Ok well the loop is easy enough to detect, it’s just the highest correlation peak, and you’ve done that already (2.66s). The BPM inside the loop is trickier. $\endgroup$
    – Jdip
    Aug 11 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.