1. 程式人生 > >語音訊號預處理及特徵引數提取

語音訊號預處理及特徵引數提取

1. WAVE檔案格式

在進行語音訊號處理時,基本上會採用WAVE檔案進行處理。WAVE檔案格式有什麼特點呢?為什麼要使用WAVE檔案呢?

1.1 資源互換檔案格式——RIFF

在windows環境下,大部分的多媒體檔案都依循著一些通用的結構來存放,這些結構稱為“資源互換檔案格式”(Resources Interchange File Format),簡稱RIFF。RIFF可以看作一種樹狀結構,其基本構成單位是塊(chunk)。每個塊由“辨別碼”、“資料大小”及“資料”等構成。
RIFF檔案的前4位元組為其辨別碼“RIFF"的ASCII字元碼,緊跟其後的雙位元組資料則標示整個檔案大小(單位為位元組Byte)。由於表示檔案長度或塊長度的”資料大小“資訊佔用4Byte,所以,事實上一個WAVE檔案或檔案中塊的長度為資料大小加8。


1.2 WAVE檔案格式

WAVE檔案格式是windows中關於聲音的一種標準格式,也是RIFF檔案格式支援的一種格式,這種格式已成為Windows中的基本聲音格式。整個WAVE檔案可以分成兩部分:前一部分為檔案頭,後一部分為資料塊。根據其編碼方式和取樣數的不同,這兩部分的大小有所不同。在WAVE檔案中,所採用的編碼方式有PCM(Pulse Code Modulation-脈衝編碼調製)和ADPCM(Adaptive Differential Pulse Code Modulation-自適應差分脈衝編碼調製)兩種。

WAVE檔案是非常簡單的一種RIFF檔案,它的格式型別為"WAVE"。RIFF塊包含兩個子塊,這兩個子塊的ID分別是"fmt"和"data",其中"fmt"子塊由結構PCMWAVEFORMAT所組成,其子塊的大小就是sizeofof(PCMWAVEFORMAT),資料組成就是PCMWAVEFORMAT結構中的資料。

下面是一個語音的資料:

下面是資料中每個位元組的內容:


2. 語音的預處理

在對語音訊號進行分析和處理之前,必須對其進行預加重、分幀、加窗等預處理操作。這些操作的目的是消除因為人類發聲器官本身和由於採集語音訊號的裝置所帶來的混疊、高次諧波失真、高頻等等因素,對語音訊號質量的影響。儘可能保證後續語音處理得到的訊號更均勻、平滑,為訊號引數提取提供優質的引數,提高語音處理質量。

2.1 預加重

語音訊號s(n)的平均功率譜受聲門激勵和口鼻輻射的影響,高頻端大約在800Hz以上按6dB/oct (倍頻程)衰減,頻率越高相應的成分越小,為此要在對語音訊號s(n)進行分析之前對其高頻部分加以提升。通常的措施是用數字濾波器實現預加重,預加重網路的輸出 和輸入的語音訊號s(n)的關係為:

其中a為預加重係數,一般取,本系統中取a= 0.9375。

單詞 interesting資料顯示


單詞 interesting資料經預加重後

2.2 分幀

貫穿於語音分析全過程的是“短時分析技術”。語音訊號具有時變特性,但是在一個短時間範圍內(一般認為在10~30ms的短時間內),其特性基本保持不變即相對穩定,因而可以將其看作是一個準穩態過程,即語音訊號具有短時平穩性。所以任何語音訊號的分析和處理必須建立在“短時”的基礎上,即進行“短時分析”,將語音訊號分段來分析其特徵引數,其中每一段稱為一“幀”,幀長一般取為10~30ms。這樣,對於整體的語音訊號來講,分析出的是由每一幀特徵引數組成的特徵引數時間序列。


2.3 加窗

由於語音訊號具有短時平穩性,我們可以對訊號進行分幀處理。緊接著還要對其加窗處理。窗的目的是可以認為對抽樣n附近的語音波形加以強調而對波形的其餘部分加以減弱。對語音訊號的各個短段進行處理,實際上就是對各個短段進行某種變換或施以某種運算。用得最多的三種窗函式是矩形窗、漢明窗(Hamming)和漢寧窗(Hanning),其定義分別為:
矩形窗和漢明窗的比較:
矩形窗,主瓣較窄,具有較高的頻率解析度,但具有較高的旁瓣,相鄰諧波干擾比較嚴重。與矩形窗相比,漢明窗得到的頻譜卻要平滑得多。

2.4 端點檢測

2.4.1 短時能量

短時能量序列反映了語音振幅或能量隨著時間緩慢變化的規律 

2.4.2 過零率


語音訊號處理中的端點檢測主要是為了自動檢測出語音的起始點及結束點。

這裡我們採用了雙門限比較法來進行端點檢測。雙門限比較法以短時能量E和短時平均過零率Z作為特徵,結合Z和E的優點,使檢測更為準確,有效降低系統的處理時間,能排除無聲段的噪聲干擾,從而提高的語音訊號的處理效能。


function [x1,x2] = vad(x)

%幅度歸一化到[-1,1]
x = double(x);
x = x / max(abs(x));

%常數設定
FrameLen = 240;
FrameInc = 80;

amp1 = 10;
amp2 = 2;
zcr1 = 10;
zcr2 = 5;

maxsilence = 8;  % 6*10ms  = 30ms
minlen  = 15;    % 15*10ms = 150ms
status  = 0;
count   = 0;
silence = 0;

%計算過零率
tmp1  = enframe(x(1:end-1), FrameLen, FrameInc);
tmp2  = enframe(x(2:end)  , FrameLen, FrameInc);
signs = (tmp1.*tmp2)<0;
diffs = (tmp1 -tmp2)>0.02;
zcr   = sum(signs.*diffs, 2);

%計算短時能量
amp = sum(abs(enframe(filter([1 -0.9375], 1, x), FrameLen, FrameInc)), 2);

%調整能量門限
amp1 = min(amp1, max(amp)/4);
amp2 = min(amp2, max(amp)/8);

%開始端點檢測
x1 = 0; 
x2 = 0;
for n=1:length(zcr)
   goto = 0;
   switch status
   case {0,1}                   % 0 = 靜音, 1 = 可能開始
      if amp(n) > amp1          % 確信進入語音段
         x1 = max(n-count-1,1);
         status  = 2;
         silence = 0;
         count   = count + 1;
      elseif amp(n) > amp2 | ... % 可能處於語音段
             zcr(n) > zcr2
         status = 1;
         count  = count + 1;
      else                       % 靜音狀態
         status  = 0;
         count   = 0;
      end
   case 2,                       % 2 = 語音段
      if amp(n) > amp2 | ...     % 保持在語音段
         zcr(n) > zcr2
         count = count + 1;
      else                       % 語音將結束
         silence = silence+1;
         if silence < maxsilence % 靜音還不夠長,尚未結束
            count  = count + 1;
         elseif count < minlen   % 語音長度太短,認為是噪聲
            status  = 0;
            silence = 0;
            count   = 0;
         else                    % 語音結束
            status  = 3;
         end
      end
   case 3,
      break;
   end
end   

count = count-silence/2;
x2 = x1 + count -1;

subplot(311)
plot(x)
axis([1 length(x) -1 1])
ylabel('Speech');
line([x1*FrameInc x1*FrameInc], [-1 1], 'Color', 'red');
line([x2*FrameInc x2*FrameInc], [-1 1], 'Color', 'red');

subplot(312)
plot(amp);
axis([1 length(amp) 0 max(amp)])
ylabel('Energy');
line([x1 x1], [min(amp),max(amp)], 'Color', 'red');
line([x2 x2], [min(amp),max(amp)], 'Color', 'red');

subplot(313)
plot(zcr);
axis([1 length(zcr) 0 max(zcr)])
ylabel('ZCR');
line([x1 x1], [min(zcr),max(zcr)], 'Color', 'red');
line([x2 x2], [min(zcr),max(zcr)], 'Color', 'red');


3. MFCC特徵引數提取


什麼是語音的特徵引數?特徵引數包括什麼?怎麼提取?
在語音訊號中,包含著非常豐富的特徵引數,不同的特徵向量表徵著不同的物理和聲學意義。選擇什麼特徵引數對說話人識別系統的成敗意義重大。如果選擇了好的特徵引數,將有助於提高識別率。特徵提取就是要儘量取出或削減語音訊號中與識別無關的資訊的影響,減少後續識別階段需處理的資料量,生成表徵語音訊號中攜帶的說話人資訊的特徵引數。根據語音特徵的不同用途,需要提取不同的特徵引數,從而保證識別的準確率。

常用的語音特徵引數有LPCC 和MFCC。LPCC 引數是根據聲管模型建立的特徵引數, 主要反映聲道響應。MFCC 引數是基於人的聽覺特性利用人聽覺的臨界帶效應, 在Mel 標度頻率域提取出來的倒譜特徵引數。

Mel倒譜系數是根據人類聽覺系統的特性提出的,模擬人耳對不同頻率語音的感知。人耳分辨聲音訊率的過程就像一種取對數的操作。例如:在Mel頻域內,人對音調的感知能力為線性關係,如果兩段語音的Mel頻率差兩倍,則人在感知上也差兩倍。

MFCC演算法過程:

(1) 快速傅立葉變換(FFT)


(2) 將實際頻率尺度轉換為Mel頻率尺度:


(3) 配置三角形濾波器組並計算每一個三角形濾波器對訊號幅度譜濾波後的輸出:


(4) 對所有濾波器輸出作對數運算,再進一步做離散餘弦變換(DTC),即可得到MFCC:

function ccc = mfcc(x)
% 歸一化mel濾波器組係數
bank=melbankm(24,256,8000,0,0.5,'m');
bank=full(bank);
bank=bank/max(bank(:));

% DCT係數,12*24
for k=1:12
  n=0:23;
  dctcoef(k,:)=cos((2*n+1)*k*pi/(2*24));
end

% 歸一化倒譜提升視窗
w = 1 + 6 * sin(pi * [1:12] ./ 12);
w = w/max(w);

% 預加重濾波器
xx=double(x);
xx=filter([1 -0.9375],1,xx);

% 語音訊號分幀
xx=enframe(xx,256,80);

% 計算每幀的MFCC引數
for i=1:size(xx,1)
  y = xx(i,:);
  s = y' .* hamming(256);
  t = abs(fft(s));
  t = t.^2;
  c1=dctcoef * log(bank * t(1:129));
  c2 = c1.*w';
  m(i,:)=c2';
end

%差分系數
dtm = zeros(size(m));
for i=3:size(m,1)-2
  dtm(i,:) = -2*m(i-2,:) - m(i-1,:) + m(i+1,:) + 2*m(i+2,:);
end
dtm = dtm / 3;

%合併mfcc引數和一階差分mfcc引數
ccc = [m dtm];
%去除首尾兩幀,因為這兩幀的一階差分引數為0
ccc = ccc(3:size(m,1)-2,:);