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');
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');
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');
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





