语音信号处理#1 短时时域分析

本文最后更新于:2022年7月21日 下午

语音信号处理#1 短时时域分析

**在分析视频的时候,我们通常是分帧进行分析,类比到对语音的分析,我们一般也是划分音频帧进行分析,这就是短时分析,**这一篇文章先介绍短时的时域分析。

“短时”究竟有多短呢?一般取10ms~30ms,具体要取多少采样点和采样率有关系。

那么我们如何进行音频分帧呢?如下图分成分帧加窗两步。每一帧会有重叠(overlap),因为音频信号不像视频信号一样容易分帧。而在信号与系统里面学过分帧以后加窗更有利于之后的分析,可以看作是给一个音频帧加权,越中间的信号越重要。

窗一般用汉明窗(Hamming)w(n)=0.540.46cos(2πnN1),0nNw(n)=0.54-0.46\cos (\frac{2\pi n}{N-1}), 0\le n \le N

分帧加窗之后,就能得到固定采样点的信号了(N\boldsymbol{N}点),在时域上我们经常进行短时平均能量、短时平均幅度、短时平均过零率、短时自相关、短时平均幅度差的分析

  1. 短时平均能量

    帧内每个点的平方和

  2. 短时平均幅度

    帧内每个点的绝对值的和

  3. 短时平均过零率

    假如一个信号先正后负或者先负后正就说明产生了一次过零,检测方法如下

    graph LR
    A[原始信号] --> B(取sgn 正1负-1)
    B --> C(一阶差分 后-前)
    C --> D(取绝对值)
    D --> E(求和取平均)
    

    Zn=12Nm=nN+1nsgn[x(m)]sgm[x(m1)]Z_n=\frac{1}{2N}\sum^n_{m=n-N+1}|sgn[x(m)]-sgm[x(m-1)]|

  4. 短时自相关函数

    就是把信号往右挪kk步然后和原信号相乘求和的值,然后把kk作为变量的函数。

    可以使用自相关函数求浊音语音的基音周期,因为自相关函数值越大就表示位移后的信号和原来信号越接近,所以当基音周期存在时,每过一个周期就会出现一个最大值。

    Rn(k)=m=0N1kxn(m)xn(m+k)(0kK)R_n(k)=\sum^{N-1-k}_{m=0}x_n(m)x_n(m+k)\quad (0\le k \le K)

  5. 短时平均幅度差函数

    乘积更难算,所以把自相关的乘改成了差

    Fn(k)=m=0N1kxn(m)xn(m+k)F_n(k)=\sum^{N-1-k}_{m=0}|x_n(m)-x_n(m+k)|

MATLAB代码实现

示例音频下载 百度网盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
clear all
close all
clc

%% 分帧
% 输入文件
input_audio = 'F717.wav';
% 读取
[x,Fs] = audioread(input_audio);
[len,d] = size(x);
time = (0:len-1) / Fs;
% 配置
frame_second = 10; % ms
overlap_percent = 0.5;
frame_size = floor(Fs * 0.001 * frame_second);
overlap = floor(overlap_percent * frame_size);
% 分帧
for n = 1:(frame_size-overlap):len-frame_size
num = (n-1) / (frame_size-overlap) + 1;
y(:,num) = x(n:n+frame_size-1);
end
[d,frame_num] = size(y);
frame_time = (0: frame_num-1) * frame_second;

%% 短时平均幅度特性
S = sum(abs(y), 1);

%% 短时能量
E = sum(y.*y, 1);

%% 短时过零率
y1 = sign(y(:,1:frame_num-1));
y2 = sign(y(:,2:frame_num));
yy = sum(abs(y2 - y1), 1) / 2 / d;

%% 短时自相关
% 取一帧进行展示
n = 10;
acf = autocorr(y(:,n), frame_size-1);
[pks,locs] = findpeaks(acf);

%% 展示
subplot(311);
plot (time, x); grid on; title('输入波形'); xlabel(['时间/s']);
axis([0 time(end) -1 1]);

subplot(334);
plot (frame_time, S); grid on; title('短时平均幅度特性');xlabel(['时间/ms']);

subplot(335);
plot (frame_time, E); grid on; title('短时能量');xlabel(['时间/ms']);

subplot(336);
plot (frame_time(1:end-1), yy); grid on; title('短时过零率');xlabel(['时间/ms']);

subplot(313);
plot(time(1: frame_size)*1000, acf); title('短时自相关');xlabel(['时间/ms']); hold on;
scatter(time(locs)*1000, pks); hold off;
% 基音频率 单位Hz
1000 / (locs(pks==max(pks)) / frame_size * frame_second)