| [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
|
|