Objective: Finding the BPM of a short drum loop.
% 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);
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.
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.
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;
>> 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