[Matlab] Pitch Frequency Estimation

Bu projede Matlab ortamında, önceden kaydedilmiş olan bir bayan sesinin “Pitch Frequency” analizi yapılarak segmentasyon işlemi gerçekleştirilmiş ve sesli/sessiz segmentler ayırt edilerek sinyalin sesli segmentlerinin ortalaması çıkarılmıştır. Proje, ses tanıma algoritmalarına giriş niteliğinde bir ön bilgi olarak sayılabilir.

İçerik

  • Değişkenlerin Tanımlanması
  • İşlenecek Sinyalin Matlab Ortamına Alınması
  • Sinyalden DC Bileşenlerin Atılması
  • Segmentasyonda Kullanılacak Değişkenlerin Belirlenmesi
  • Silence Analizi İçin Gerekli Değişkenlerin Bulunması
  • Silence Olan Segmentlerin Atılması
  • Clipping Level Parametrelerinin Elde Edilmesi
  • Segmentlerin Enerjilerinin ve Otokorelasyonlarının Bulunması
  • Sonuç

Değişkenlerin Tanımlanması

Programda kullanılacak değişkenler hız kazanmak için önceden tanımlanıyor.

xseg_son=[];
mm_son=[];
cc=[];
energy=[];
pitch=[];
voiced=[];
unvoiced=[];

İşlenecek Sinyalin Matlab Ortamına Alınması
normal_female.wav dosyası x değişkenine atiliyor. Okunan sinyalin sample frekansı fs değişkeninde tutuluyor. x değişkenine atanmış olan sinyal plot ediliyor.

[x,fs]=wavread('normal_female');
close all
plot(x);
title('Okunan Sinyal');
Okunan Sinyal

Okunan Sinyal

Sinyalden DC Bileşenlerin Atılması

Sinyalin mean değeri kendinden çıkarılarak DC bileşenler atiliyor. Sonuç X değişkenine atılarak çizdiriliyor.

X=x-mean(x);
plot(X);
title('DC Bileseni Atilmis Sinyal Sinyal');
DC Bileseni Atilmis Sinyal

DC Bileseni Atilmis Sinyal

Segmentasyonda Kullanılacak Değişkenlerin Belirlenmesi

Bu kısımda segmentasyon işleminde kullanılacak parametreler belirlenip ardından buffer komutu ile belirlenen block değerlerinde segmentlere bölme işlemi gerçekleştiriliyor. Window’lar overlap miktarı kadar çakışık olarak bölünmektedir. Ardından elde edilen window’lar hamming window ile çarpılarak segmentler elde ediliyor.

block=30*fs/1000; % Segmentlerin block uzunluğunun okunan sinyalin sample frekansından bulunması
overlap=10*fs/1000;% Overlap miktarının bulunması.
xson=buffer(X,block,overlap);% Segmentasyon yapılıyor.
xson=xson.*repmat((hamming(block)),1,length(xson(1,:)));% Hamming Code İle Çarpım.

Silence Analizi İçin Gerekli Değişkenlerin Bulunması

Sinyalin sesli/sessiz kısımlarının analizi için gerekli bazı değişkenlerin tanımlamaları yapılıyor.

Maximum=max(X);% DC bileşenleri atılmış sinyalin maximum değeri bulunuyor.(Global Maximum)
maxy=(Maximum*0.05);% Silence için threshold değeri tanımlanıyor
sinyal_uz=length(xson(1,:)); % xson sinyalinin boyutları [1500,300].Burada sinyal_uz 300 değerini alıyor.

Silence Olan Segmentlerin Atılması

Aşağıdaki döngüde silence olmayan segmentler hesaplanıyor. Her segmentin maximum değeri xseg_max değişkenine atanıyor. Bu değişken de threshold değerimiz olan maxy ile karşılaştırılıyor. Silence olmayan bir değer bulunduğunda ise z değeri 1 arttırılıyor.

z=1;% Silence olmayan segmentlerin sayısını z verecek
for c=1:(sinyal_uz), % sinyal_uz=300.% Her segmentin maximumu xseg_max a atanıyor.
% Bir sonraki adımda global max. ile karşılaştırılacak.
xseg_max=max(xson(:,c));
if xseg_max >maxy % Segmentin maximumu global maximum ile karşılaştırılıyor.
xseg_son(:,z)=xson(:,c); % Silencelardan arındırılmış yeni bir "xseg_son" sinyali oluşturuluyor.
z=z+1; % Silence olmayan her segment için z 1 arttırılıyor.
else
end % if
end % for
 
xx=xseg_son(:,1:(z-1)); % xseg_son xx e atandı.
plot(xx(:));
title('Silence Atilmis Sinyal');
Silence Atilmis Sinyal

Silence Atilmis Sinyal

Clipping Level Parametrelerinin Elde Edilmesi

Aşağıdaki döngüde her segmentin ilk ve son üçte birlik kısmının maximumu bulunup karşılaştırılıyor. Bu karşılaştırılan iki değerden de küçük olanı mm değişkenine atanıyor. Clipping Level ı tanımlamak amacıyla elde edilen değer de 0,68 ile çarpılıyor. Segmentin bu değerden büyük olan elemanlarından bu threshold değeri çıkarılıyor. Küçük olan değerler ise doğrudan 0′a yuvarlanıyor.

for i=1:length(xx(1,:)), %i=1:300
m1=max(abs(xx(1:500,i))); % xx sinyalinin ilk 1/3 kısmının maximum elemanı bulundu
m2=max(abs(xx(1001:1500,i))); % xx sinyalinin son 1/3 kısmının maximum elemanı bulundu
mm=min(m1,m2); % Bu iki maximumdan hangisinin daha küçük olduğu belirlendi
mm_son(i)=mm*0.68; % Yukarıdaki satırda elde edilen değer 0.68 ile çarpılarak "clipping level" elde edildi
 
for j=1:length(xx(:,1)), % length(xx(:,1))=1500
if abs(xx(j,i))>mm_son(i) % Clipping level ile karşılaştırma yapılıyor
cc(j,i)=sign(xx(j,i))*((abs(xx(j,i)))-(mm_son(i))); % Clipping leveldan büyük olan bileşenlerden clipping level çıkarıldı
else
cc(j,i)=0;  % Küçük olan bileşenler ise 0 a çekildi
end  % if koşulu sona erdiriliyor
end  % 2."for" döngüsü sonu
end  % 1."for" döngüsü sonu

Segmentlerin Enerjilerinin Bulunması

Yukarıdaki döngü sonunda elde edilen cc matrisinin boyutları [1500,300]. Aşağıdaki döngüde ise her bir segment için energy hesaplanıyor. Bunun için sinyalin normunun karesi her bir kolonu için hesaplanıyor. xcorr komutu ile tüm sinyalin autocorrelation’i bulunuyor. Buradan 50Hz ile 400Hz arasindaki autocorrelation bileşenleri bulunuyor ve bunlara karşılık gelen pitch frekansları hesaplanıyor.

w=1; % Voiced segmentler için başlangıç ataması
v=1; % Unvoiced sinyaller için başlangıç ataması
u=1; % Voiced olarak düşündüğümüz bileşenlerin sayısını bu parametre gösterecek
a=[]; % Autocorrelation matrisi için başlangıç ataması
for h=1:length(cc(1,:)),  % cc nin kolon sayısı=300
energy(h)=norm(cc(:,h),2)^2; % Her segment için enerji hesaplanıyor
a(:,h)=xcorr(cc(:,h));   % İlk başta bütün cc sinyalinin autocorrelation u bulunuyor
 
% 50 Hz-400Hz arasındaki autocorrelation fonksiyonu değerlerini bulabilmek için 50 Hz ve 400 Hz frekanslarına karşılık gelen pitch  frequency değerlerinin indekslerini alıyoruz.
alt_sinir=floor(fs/400);
ust_sinir=floor(fs/50);
Rxx=abs(a((block+alt_sinir:block+ust_sinir),h));
[k l]=max(Rxx);   % Aldığımız aralıktaki en büyük sayının yerini belirliyoruz
l=l+alt_sinir;
pitch(h)=fs/l;  % Pitch Frequnecy hesaplanıyor 
 
% Segmentin sesli/sessiz oldugunu bulabilmek için autocorrelation'in 0.4*energy'den
% büyük olup olmadigi karsilastiriliyor. Eger büyükse segment seslidir ve voiced
% matrisine atiliyor, eger küçükse unvoiced matrisine atiliyor. Voiced ve unvoiced
% segment sayisi w ve v degiskenlerinde tutuluyor.
 
if k > 0.4*energy(h) % En büyük değer 0.4*energy ile karşılaştırılıyor
voiced(:,w)=cc(:,h); % Şart sağlanırsa voiced sinyaline atılıyor
w=w+1; % Koşul sağlanırsa voiced segment sayısı arttırılır.
else
unvoiced(:,v)=cc(:,h); % Şart sağlanmazsa unvoiced sinyali oluşturuluyor
v=v+1; % Unvoiced sinyal segmentleri 1 arttılır.
end
end % 1. "for" döngüsü sonu

Sonuç

En son kısımda ise sesli sinyalinin ortalaması alınıyor

sesli_ort=mean(pitch); % Voiced segmentlerin ortalaması
sesli_ort
 
sesli_ort=
232.8431
Related Posts

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">