BPM analysis in a song

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

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)

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

As to the problem with your code:
Look more carefully at your
if(sig(k)<trhold && trhold<sig(k-1))
test. Inside that test, under certain conditions, you set the value of temp to 0.
However, you never use the value of temp anywhere.
Also your test
if(sig(k)>0.4)
is outside the threshold test. You are not checking whether the peak is that high: you are just testing whether each sample is that high.
Consider for example
j = k : min(k+100, brk);
peak = sum(real(sig(j)));
Replaces your for j loop.
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.

Asked:

on 11 Mar 2022

Edited:

Rik
on 17 Mar 2022

Community Treasure Hunt

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

Start Hunting!