BPM analysis in a song

21 views (last 30 days)
amjad hammad
amjad hammad on 11 Mar 2022
Edited: Rik on 17 Mar 2022
hi i am working in code to calculate in a Musical composition but i have o
[queen,fs] = audioread('Test_sound.mp3');
vyrez=queen(1:fs*30);
trhold= 0.01; % / 0.2
x = length(vyrez);
cas = round(x/fs);
nfft2=2.^nextpow2(x);
otoc=vyrez';
fy=fft(otoc,nfft2);
fy=fy(1:nfft2/2);
fy=fy';
xfft=fs.*(0:nfft2/2-1)/nfft2;
figure
subplot(2,1,1);
plot(vyrez);
title('Original snippet signal from the song ');
cut_off=1.5e3/fs/2;
order=32;
h=fir1(order,cut_off,'low');
fh=fft(h,nfft2);
fh=fh(1:nfft2/2);
mul=fh.*fy;
% subplot(2,1,2);
% plot(abs(mul));
sig=abs(ifft(mul));
subplot(2,1,2);
plot(sig);
title('Track snippet signal after filters ');
brk=size(fh); % condition of a break in the loop to bypass the error
bps=0;
peak=0;
temp=0;
but i have problem in two condition
1- condition to prevent multiple beats
2- condition for beat insertion (0.4 optimal threshold)
and any new idea for code or make it shorter or more simplely
  2 Comments
Walter Roberson
Walter Roberson on 15 Mar 2022
What difficulty are you observing? We do not have your file and you did not say what is wrong.
Rik
Rik on 17 Mar 2022
Edited: Rik on 17 Mar 2022
I recovered the removed content from the Google cache (something which anyone can do). Editing away your question is very rude. Someone spent time reading your question, understanding your issue, figuring out the solution, and writing an answer. Now you repay that kindness by ensuring that the next person with a similar question can't benefit from this answer.
This page is now archived.

Sign in to comment.

Answers (1)

Walter Roberson
Walter Roberson on 15 Mar 2022
partial correction.
[queen,fs] = audioread('Test_sound.mp3');
if size(queen,1) > fs*30
vyrez = queen(1:fs*30,1); % setting of snippet length (do not set many)
else
vyrez = queen(:,1);
end
Your old code was assuming that you had at least 30 seconds worth of sound, and was doing linear indexing. However what you really had was about 15 3/4 seconds of sound on each of two channels.
trhold= 0.01; % / 0.2
x = length(vyrez);
cas = round(x/fs);
% sound(vyrez,fs);
nfft2=2.^nextpow2(x);
otoc=vyrez';
fy=fft(otoc,nfft2);
fy=fy(1:nfft2/2);
fy=fy';
xfft=fs.*(0:nfft2/2-1)/nfft2;
figure
subplot(2,1,1);
plot(vyrez);
title('Original snippet signal from the song');
% subplot(2,1,1);
% plot(xfft,abs(fy/max(fy)));
cut_off=1.5e3/fs/2;
order=32;
h=fir1(order,cut_off,'low');
fh=fft(h,nfft2);
fh=fh(1:nfft2/2);
fh = reshape(fh, size(fy));
Your fh was coming out as a row vector, but fy is a column vector, and that was a problem.
mul=fh.*fy;
% subplot(2,1,2);
% plot(abs(mul));
sig=abs(ifft(mul));
subplot(2,1,2);
plot(sig);
title('Track snippet signal after filters');
brk=length(fh); % break condition in loop to bypass error
You were using size() with a single input parameter, but you were dealing with a row vector, so you were getting a vector [1 something] . That wasn't good for testing.
bps=0;
peak=0;
temp=0;
for k=2:length(sig)-1
% condition for preventing multiple bit insertion
if(sig(k)<trhold && trhold<sig(k-1))
You were using sig(k)<trhold<sig(k-1) which means something completely different to MATLAB
p=0;
j=k;
for j= k:k+100
p=p+real(sig(j));
end
if(p+5<peak)
temp=0;
end
end
% condition for beat inclusion (0.4 optimal threshold)
if(sig(k)>0.4)
bps=bps+1;
j=k;
for j= k+100
if(j>=brk)
break;
end
end
end
end
fprintf('There was %d beats in the song snippet %f seconds long \n', bps, cas);
You had the variables reversed for the message.
min=cas/60;
bpm=bps/min;
fprintf('BPM = %f [beat/min]\n',bpm);
figure
subplot(2,1,1);
plot(xfft,abs(fy/max(fy)));
subplot(2,1,2);
plot(abs(mul));
  3 Comments
Walter Roberson
Walter Roberson on 15 Mar 2022
Consider for example
j = k : min(k+100, brk);
peak = sum(real(sig(j)));
Replaces your for j loop.
Walter Roberson
Walter Roberson on 15 Mar 2022
Replace
if(sig(k)>0.4&&temp==0) %sig(k)>sig(k-1)&& sig(k)>sig(k+1)&&
bps=bps+1;
temp=1;
peak=0;
j=k;
for j= k:k+100
if(j>=brk)
break;
end
peak=peak+real(sig(j));
end
end
with
if(sig(k)>0.4&&temp==0) %sig(k)>sig(k-1)&& sig(k)>sig(k+1)&&
bps=bps+1;
temp=1;
j = k : min(k+100, brk);
peak = sum(real(sig(j)));
end
Recall that earlier I gave code and said that it replaces your for loop.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!