语音信号处理基础(六)——短时时域处理

3.短时时域处理

3.1 短时能量

设语音波形时域信号为x(n)、加窗函数w(n)分帧处理后得到的第i帧语音信号为yi(n),则yi(n)满足
KaTeX parse error: Undefined control sequence: \leqsl at position 58: … 1 \leqslant n \̲l̲e̲q̲s̲l̲ ̲ant L, \quad 1 …
式中,w(n)为窗函数,一般为矩形窗或汉明窗;yi(n)是一帧的数值,n=1,2…,L,i=1,
2…,fn,L为帧长;inc为帧移长度;fn为分帧后的总帧数。

计算第i帧语音信号yi(n)的短时能量公式为
E(i)=n=0L1yi2(n),1ifn E(i)=\sum_{n=0}^{L-1} y_{i}^{2}(n), \quad 1 \leqslant i \leqslant f n
例:读入语音文件C2_2_y.wav(内容为"我,到,北,京,去")中的数据,计算能量谱

实现代码

%语音分帧,平画出它的短时能量谱

clear all; clc; 
close all;

[x,Fs]=audioread('C2_2_y.wav');     % 读入数据文件

wlen=200; inc=80;          % 给出帧长和帧移
win=hanning(wlen);         % 给出海宁窗
N=length(x);               % 信号长度
X=enframe(x,win,inc)';     % 分帧
fn=size(X,2);              % 求出帧数
time=(0:N-1)/Fs;           % 计算出信号的时间刻度
for i=1 : fn
    u=X(:,i);              % 取出一帧
    u2=u.*u;               % 求出能量
    En(i)=sum(u2);         % 对一帧累加求和
end
subplot 211; plot(time,x,'b'); % 画出时间波形 
title('语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
frameTime=frame2time(fn,wlen,inc,Fs);   % 求出每帧对应的时间
subplot 212; plot(frameTime,En,'k')     % 画出短时能量图
title('短时能量');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);

运行结果
在这里插入图片描述
程序中调用了frame2time函数,用于计算分帧后每一帧对应的时间。

名称:frame2time

功能:计算分帧后每一帧对应的时间

调用格式:frameTime=frame2time(framelum,framelen,inc,fs)

说明:输入参数framelNum是总帧数;framelen是帧长;inc是帧移;fs是采样频率.输出参数frameTime是每帧的时间,即取这一帧数据中间位置的时间.

语音信号的平均幅度定义为
M(i)=n=0L1yi(n),1ifn M(i)=\sum_{n=0}^{L-1}\left|y_{i}(n)\right|, \quad 1 \leqslant i \leqslant f n
M(i)也是一帧语音信号能量大小的表征,它与E(i)的区别在于计算时不论采样值的大小,不会因取二次方而造成较大差异,在某些应用领域中会带来一些好处.
短时能量和短时平均幅度函数的主要用途有:

区分浊音段与清音段,因为浊音时E(i)值比清音时大得多;

区分声母与韵母的分界和无话段与有话段的分界

3.2短时平均过零率

短时平均过零率表示一帧语音中语音信号波形穿过横轴(零电平)的次数。过零率分析是语音时域分析中最简单的一种。对于连续语音信号,过零即意味着时域波形通过时间轴;而对于离散信号,如果相邻的取样值改变符号,则称为过零。短时平均过零率就是样本数值改变符号的次数。

定义语音信号x(n)分帧后有yi(n),帧长为L,短时平均过零率为
Z(i)=12n=0L1sgn[yi(n)]sgn[yi(n1)],1ifn Z(i)=\frac{1}{2} \sum_{n=0}^{L-1}\left|\operatorname{sgn}\left[y_{i}(n)\right]-\operatorname{sgn}\left[y_{i}(n-1)\right]\right|, \quad 1 \leqslant i \leqslant f n
理论上平均过零率按上式计算,但在MATLAB中,可表示为离散信号相邻的取样值改变符号,那么它们的乘积为负数
yi(n)yi(n+1)<0 y_{i}(n) y_{i}(n+1)<0
将语音信号分帧,分帧后的数组为X,其中每列数据表示一帧的数值,帧长为wlen,用zcr表示短时平均过零率

实现代码

zcr=zeros(1,fn);           %初始化
fori=1:fn 
   z=X(:,i);               %取得一帧数据
   forj=1:(wlen-1);        %在一帧内寻找过零点
      if z(j)*z(j+1)<0     %判断是否为过零点
         zcr(i)=zcr(i)+1;  %是过零点,记录1次
      end
   end
end

例 读入语音文件C2_2_y.wav(内容为“我,到,北,京,去”)中的数据,分帧后计算短时平均过零率。

实现代码

%短时平均过零率
clear all; clc; close all;

[xx,Fs]=audioread('C2_2_y.wav');  % 读入数据文件
x=xx-mean(xx);                    % 消除直流分量
wlen=200; inc=80;                 % 设置帧长、帧移
win=hanning(wlen);                % 窗函数
N=length(x);                      % 求数据长度
X=enframe(x,win,inc)';            % 分帧
fn=size(X,2);                     % 获取帧数
zcr1=zeros(1,fn);                 % 初始化
for i=1:fn
    z=X(:,i);                     % 取得一帧数据
    for j=1: (wlen- 1)            % 在一帧内寻找过零点
         if z(j)* z(j+1)< 0       % 判断是否为过零点
             zcr1(i)=zcr1(i)+1;   % 是过零点,记录1次
         end
    end
end
time=(0:N-1)/Fs;                  % 计算时间座标
frameTime=frame2time(fn,wlen,inc,Fs);  % 求出每帧对应的时间
% 作图
subplot 211; plot(time,x,'b'); grid;
title('语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
subplot 212; plot(frameTime,zcr1,'k'); grid;
title('短时平均过零率');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);

运行结果


通过分析语音信号发现,发浊音时,尽管声道有若干共振峰,但由于声门波引起谱的高频跌落;而发清音时,多数能量出现在较高频率上。因为高频意味着高的短时平均过零率,低频意味着低的平均过零率,所以认为,浊音时具有较低的过零率,而清音时具有较高的过零率(相当于白噪声)。这种高仅是相对而言的,没有精确的数值关系。

应用短时平均过零率的作用

利用短时平均过零率可以从背景噪声中找出语音信号,可用于判断寂静无话段与有话段的起点和终点位置。

在背景噪声较小时,用平均能量识别较为有效

在背景噪声较大时,用短时平均过零率识别较为有效

主要应用短时平均过零率来判别清音和浊音、有话段与无话段

3.3短时自相关函数

1.自相关函数的定义和性质
能量有限信号x(n)的自相关函数定义为
Φ(k)=m=x(m)x(m+k) \Phi(k)=\sum_{m=-\infty}^{\infty} x(m) x(m+k)
如果x(n)是随机或周期性的离散信号,不是能量有限的,则其相关函数定义为
Φ(k)=limN12N+1m=NNx(m)x(m+k) \Phi(k)=\lim _{N \rightarrow \infty} \frac{1}{2 N+1} \sum_{m=-N}^{N} x(m) x(m+k)
信号的自相关函数具有以下性质

①偶函数特性:Ф(k)=Ф((一k).
②| Ф(k)|<|Ф(0)|,即零延迟的自相关值最大.
③若x(n)为能量有限信号,则其能量即为Ф(0);若x(n)为随机信号或周期性信号,则Ф(0)为其平均功率.
④如果x(n)是周期性信号,则Ф(k)也是周期性信号,并且其周期与x(n)的周期相同.

2.短时自相关函数的定义和性质

自相关函数具有一些性质(如它是偶函数;假设序列具有周期性,则其自相关函数也是同周期的周期函数等)。对于浊音语音可以用自相关函数求出语音波形序列的基音周期。在进行语音信号的线性预测分析时,也要用到自相关函数。语音信号x(m)的短时自相关函数R(k))的计算式如下:
Rn(k)=m=0N1kxn(m)xn(m+k)(0kK) R_{n}(k)=\sum_{m=0}^{N-1-k} x_{n}(m) x_{n}(m+k) \quad(0 \leq k\leq K)
其中N表示为语音分帧的长度,K表示最大延迟数

短时自相关函数具有以下性质:

(1)如果Xn(m)是周期的(设周期为Np),则自相关函数是同周期的周期函数,即Rn(k)=Rn(k+Np)

(2)Rn(k)是偶函数,即Rn(k)+Rn(-k)

(3)当k=0时,自相关函数具有最大值,即Rn(0)>=| Rn(k) |,并且Rn(0)为信号序列的能量或随机性序列的平均功率

语音信号的自相关函数主要应用于端点检测基音的提取,在韵母基音频率整数倍处将出现峰值特性,通常根据除Rτ(0)外的第一峰值点来估计基音,而在声母的短时自相关函数中看不到明显的峰值。

若已知分帧后的数据在 中,则取每一帧的数据都可以来做短时自相关函数的分析:

u=X(:,i);         %取出一帧
R=xcorr(u);       %利用xcorr函数求出自相关函数
R=R(wlen:end);    %只取k值为正值的自相关函数

例,实现一段语音信号的短时自相关(使用汉宁窗窗函数的情况,读取“我,到,北,京, 去”,设置帧长为200,帧移为80

实现代码

%短时自相关函数
clear all; clc; close all;

[Y,Fs]=audioread('C2_2_y.wav');   % 读入数据文件
x=Y-mean(Y);                      % 消除直流分量
wlen=200; inc=80;                 % 设置帧长、帧移
win=hanning(wlen);                % 窗函数设置为汉宁窗
N=length(x);                      % 求数据长度
X=enframe(x,win,inc)';            % 分帧
xn=X(:);
Ac1=STAc(X);                      %计算短时自相关函数
Ac1=Ac1(:);
time=(0:N-1)/Fs;                  % 计算时间座标

% 作图
subplot 211; 
plot(xn,'b'); grid;
title('语音波形');
ylabel('幅值'); xlabel(['时间/s' 10 '(a)']);
subplot 212; 
plot(Ac1,'k'); 
grid;
title('短时自相关函数');
ylabel('幅值'); xlabel(['时间/s' 10 '(b)']);

%定义短时自相关函数
function y=STAc(X)
y=zeros(size(X));
fn=size(X,2);                     %求出帧数
wlen=size(X,1);                   %求帧长
   for i=1:fn 
       u=X(:,i);                  %取出一帧
       R=xcorr(u);                %短时自相关计算
       y(:,i)=R(wlen,end);     %只取k为正值的自相关函数
   end
end

运行结果

3.4短时平均幅度差

短时自相关函数是语音信号时域分析的重要参量。
但是计算自相关函数的计算量很大,其乘法运算所需时间较长。利用FFT等简化计算方法都无法避免乘法运算。为了避免乘法,一个简单的方法就是利用差值。所以采用另一种与自相关函数有类似作用的参量,即短时平均幅度差函数。
平均幅度差函数代替自相关函数进行语音分析的原因是:如果信号是完全的周期信号(设周期为Np),则相距为周期的整数倍的样点上的幅值是相等的,差值为零。
d(n)=x(n)x(n+k)=0(k=0,±Np,±2Np,) d(n)=x(n)-x(n+k)=0 \quad\left(k=0, \pm N_{p}, \pm 2 N_{p}, \cdots\right)
对于实际的语音信号,d(n)虽不为零,但其值很小。这些极小值将出现在整数倍周期的位置上。为此,可定义短时平均幅度差函数:
Fn(k)=m=0N1kxn(m)xn(m+k) F_{n}(k)=\sum_{m=0}^{N-1-k}\left|x_{n}(m)-x_{n}(m+k)\right|
平均幅度差函数和自相关函数有密切的关系,两者之间的关系可由下式表达:
Fn(k)=2β(k)[Rn(0)Rn(k)]1/2 F_{n}(k)=\sqrt{2} \beta(k)\left[R_{n}(0)-R_{n}(k)\right]^{1 / 2}
β(k)对不同的语音段在0.6-1.0之间变化,但是对一个特定的语音段,它随k值变化并不明显。

显然,计算Fn(k)只需加、减法和取绝对值的运算,与自相关函数的加法与乘法相比,其运算量大大减少,尤其在用硬件实现语音信号分析时有很大好处。

例,实现一段语音信号的短时平均幅度差(使用汉宁窗窗函数的情况,读取“我,到,北,京, 去”,设置帧长为200,帧移为100

实现代码

%短时平均幅度差
clear all; clc; close all;

[Y,Fs]=audioread('C2_2_y.wav');   % 读入数据文件
wlen=200; inc=100;                % 设置帧长、帧移
win=hanning(wlen);                % 窗函数设置为汉宁窗
N=length(Y);                      % 求数据长度
X=enframe(Y,win,inc)';            % 分帧
xn=X(:);
Amdf=STAmdf(X);                   %计算短时幅度差
Amdf=Amdf(:);
time=(0:N-1)/Fs;                  % 计算时间座标

% 作图
subplot 211; 
plot(xn,'b'); grid;
title('语音波形');
ylabel('幅值'); xlabel(['点数' 10]);
subplot 212; 
plot(Amdf,'k'); 
grid;
title('短时平均幅度差');
ylabel('幅值'); xlabel(['点数' 10]);


%短时平均幅度差函数
function y=STAmdf(X)
y=zeros(size(X));
fn=size(X,2);          %帧数
wlen=size(X,1);        %帧长
 for i=1:fn
     u=X(:,i);         %取出一帧
     for k=1:wlen 
         y(:,k)=sum(abs(u(k:end)-u(1:end-k+1)));%求每个样本点的幅度差
     end
 end
end

运行结果
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章