image thumbnail
from Penarayuz by Ozgur Emekli
Tool (GUI) for music audio transcription

[onset ostidx oftidx]=penfrekall_tv2(n,w,mindur,fs,data,noise)
function [onset ostidx oftidx]=penfrekall_tv2(n,w,mindur,fs,data,noise)

% n: leriye dnk pencere says
% w: Pencere genilii (rnek says cinsinden)
% mindur: Kabul olarak, en kk nota sresi (ms)
% fs: rnekleme frekans
%%%%
% Bu fonksiyon, ses verisine ilikin onset ve offset anlarn gndermektedir. 
% Yazan: Ali zgr Emekli, Eyll 2006

%% ift kanall kaytlar iin, sadece ilk kanal alnyor:
if min(length(data))>=2
    data=data(:,1);
end


%%
%profile on
f=frekspektrum(w,data);
%profile off
%Pencerelere ilikin fft nceden hesaplanp, f olarak kaydediliyor, bylece hz kazanlacak...
%%

% lk 1 sn. veya kullancnn manuel olarak gnderdii noise deeri 
% kayttaki dip sesin std almak iin kullanlyor. Ancak
% bu ilem veri >0 haline getirildikten sonra yaplyor. Bu deer, offset
% tespitinde kullanlacak.
if noise==[]
noise=std(data(1:fs)-min(data(1:fs))); 
end

%% 
data=data-mean(data); % Veri, ortalamas 0 sfr olacak ekle getiriliyor...

minpen=ceil(mindur*fs/w/1e3); % minpen: iki pencere arasnda olmas gereken en az uzaklk (pencere says cinsinden).

%% %%%%%%%%%% ONSET-OFFSET ANLARININ HESABI  %%%%%%%%%%%%%%%%%%%
% Her bir pencere iin n pencere kadar ilerisi ile hesap yaplyor:
for a=1:w:length(data)-w*n
    [stdf(1+((a-1)/w)) onset(1+((a-1)/w))]=penfrek_tv2(a,n,w,fs,data,noise,minpen,f);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% %%%%%%%%%% ONSET ANLARININ LENMES %%%%%%%%%%%%%%%%%
% Btn onset anlar:
[ost,ostidxall]=find(onset==1);



% minpen'den kk aralkl onsetlerin iptal edilmesi yordam. nce iptal
% edilecek onsetler ostidx1 deikeninde 1 olarak yazlyor, daha sonra
% ostidx'de karlk den elemanlar siliniyor:

ostidx1=zeros(1,length(ostidxall));

for b=2:length(ostidxall)
    

    if ostidxall(b)-ostidxall(b-1)<=minpen
        
        ostidx1(b)=1;
  
    end
    
end

ostidxall(ostidx1==1)=[];
ostidx=ostidxall;
        
%% %%%% OFFSET ANLARININ ANALZ %%%%%%%%%%%%%%%%
% Bir ses verisinde, iki tr durum sz konusu olabilir: Sus var veya sus
% yok. Yani notalar birbiri ardna m alnyor, yoksa en az bir tane nota
% arasnda boluk var m ?
% Bizim algoritmamz, ses kaydnn bozucu etkilerinin (grlt) zamanla
% deimeyen olduu varsaymna dayanyor. Her ses kaydnda, ses iareti
% balamadan nce en az 1 sn. sresince grlt kaydediliyor. Daha sonra bu
% ksm >0 olacak eklide normalletiriliyor ve std hesaplanyor. Karar verme
% aamasnda ise, herhangi bir pencerenin std deeri, bu std'nin 2 katndan
% daha kkse, bu pencerenin sus olduuna karar veriliyor.
% Yordam, genelde her notadan sonra offset tespit ediyor, dolaysyla min
% sus zaman uzunluununun girilmesi lazm ki belli uzunluktan kk suslar
% iptal etsin. 

[ost,oftidxall]=find(onset==-1);


for c=2:length(oftidxall)
 
    fark=oftidxall(c)-oftidxall(c-1);
% ki offset noktas -1 arasnda 1 pencereden byk ancak minpen uzunluundan
% kk fark var ise, bu iki offset noktas arasn -1 yapyoruz. Yani
% bunlarn arasnda sus var diye iaretliyoruz.

    if fark<minpen && fark>1
       onset(linspace(oftidxall(c)-(fark-1),oftidxall(c)-1,fark-1))=-1;
    end


end

% Benzer ekilde, 0'lar iin de ayns yaplyor. 
[ost,zidxall]=find(onset>=0); % Buras == mi olacak ?

for d=2:length(zidxall)
 
    fark=zidxall(d)-zidxall(d-1);
    
    if fark<minpen && fark>1
       onset(linspace(zidxall(d)-(fark-1),zidxall(d)-1,fark-1))=0;
    end


end

[ost,oftidxall]=find(onset==-1);

%% %%%%% ONSET VE OFFSETLERN BRLKTE LENMES... SON KISIM... 
% Bu ksm sonunda, her bir notann balang biti anlar retilir...

for e=1:length(ostidx)
%     try
    [temp1 temp2] =find(oftidxall>ostidx(e),1,'first');
    [temp3 temp4]=find(ostidx>ostidx(e),1,'first');
    
    if isempty(temp4)
        oftidx(e)=oftidxall(temp2);
    elseif isempty(temp2)
        oftidx(e)=ostidx(temp4);
    else

    oftidx(e)=min(oftidxall(temp2),ostidx(temp4));
    end
%     catch
%         disp('Bir hata olutu')
%         dbstop
%     end
    
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Grafik izdirme ksm


cla;plot(data/max(data)), hold on,plot(ostidx*w,zeros(1,length(ostidx)),'r+');
hold on;plot(oftidx*w,zeros(1,length(oftidx)),'rx');
xlabel('Samples');
ylabel('Sound Level (Volts)');




%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [sopen,onst]=penfrek_tv2(a,n,w,fs,data,noise,minpen,fall)
% a: Pencerenin balangc n: pencere says w: pencere genilii
% data: Pencerelenecek veri fall: Tm pencelere ilikin ftt deerleri



% Buradaki yordammz u ekilde: a ile balayan pencereden itibaren n
% pencere ilerisine kadar hanning window ile fft alnyor. Her bir fft'nin
% 100-2000 Hz arasnn max deeri bulunuyor. Bu max'larn standart
% sapmalar alnyor. Standart sapma <2 ise pein olarak bu pencerede
% frekans deiiklii olmadna hkmediliyor. Standart sapma >2 ise bu
% sefer alt yordam balyor. Alt yordamda, onset iin, fmx(1)+sopen<fmx(2) koulu
% offset iinse, std(data(a:a+w-1))<2*noise koulu aranyor. Sonu olarak,
% eer a ile balayan pencere, onset olarak belirlenmise 1, offset olarak
% belirlenmise -1, hi biri deilse 0 dndrlyor. Sus'larn tespiti iin, offset halinde
% u ekilde bir algoritma tasarlyoruz: eer arka arkaya mindur saysndan
% daha byk offset belirlersek bu aral Sus olarak kaydediyoruz. 

%% rnek says cinsinden gelen a, pencere numaras cinsine dntrlyor
a=(a-1)/w+1;


%% Data'nn sonunda hata olmamas iin, data'nn sonundan n pencere
% ncesinde ilem durduruluyor
[temp1,temp2]=size(fall);
if a>temp2-n
    sopen=0; onst=0;
    return
end
%% Hesab yaplacak n pencerenin fft'leri fall'dan f deikenine ekiliyor 
for i=1:n
    
f(:,i)=fall(:,a+i-1);

end

%% Her bir pencere iin frekans spektrumunun max deeri fmx:
fmx=max(f(ceil(w/fs*100):round(w/fs*2000),:));

% std hesab
sopen=std(fmx);

% Offset tespiti
if std(data(a*w+1:(a+1)*w)-min(data(a*w+1:(a+1)*w)))<2*noise 
        
        onst=-1;
        %disp('offset')

% Onset tespiti
elseif sopen>1
       
    if fmx(1)+sopen<fmx(2)
        %disp('onset')
    onst=1;

    else
    onst=0;
    end

else
    onst=0;
end
    

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function f=frekspektrum(w,data)
% Bu fonksiyon, tm pencelerin abs(fft)sini nceden hesaplayp kaydeder,
% hz art iin.
n=round(length(data)/w)-2;
for i=1:n        
    f(:,i)=abs(fft(hann(w).*data((i-1)*w+1:i*w)));
end

Contact us at files@mathworks.com