本文最后更新于:2022年7月21日 下午
语音信号处理#1 短时时域分析
**在分析视频的时候,我们通常是分帧进行分析,类比到对语音的分析,我们一般也是划分音频帧进行分析,这就是短时分析,**这一篇文章先介绍短时的时域分析。
“短时”究竟有多短呢?一般取10ms~30ms
,具体要取多少采样点和采样率有关系。
那么我们如何进行音频分帧呢?如下图分成分帧
和加窗
两步。每一帧会有重叠(overlap),因为音频信号不像视频信号一样容易分帧。而在信号与系统里面学过分帧以后加窗更有利于之后的分析,可以看作是给一个音频帧加权,越中间的信号越重要。
窗一般用汉明窗(Hamming):w(n)=0.54−0.46cos(N−12πn),0≤n≤N。
分帧加窗之后,就能得到固定采样点的信号了(N点),在时域上我们经常进行短时平均能量、短时平均幅度、短时平均过零率、短时自相关、短时平均幅度差的分析
-
短时平均能量
帧内每个点的平方和
-
短时平均幅度
帧内每个点的绝对值的和
-
短时平均过零率
假如一个信号先正后负或者先负后正就说明产生了一次过零,检测方法如下
graph LR
A[原始信号] --> B(取sgn 正1负-1)
B --> C(一阶差分 后-前)
C --> D(取绝对值)
D --> E(求和取平均)
Zn=2N1m=n−N+1∑n∣sgn[x(m)]−sgm[x(m−1)]∣
-
短时自相关函数
就是把信号往右挪k步然后和原信号相乘求和的值,然后把k作为变量的函数。
可以使用自相关函数求浊音语音的基音周期,因为自相关函数值越大就表示位移后的信号和原来信号越接近,所以当基音周期存在时,每过一个周期就会出现一个最大值。
Rn(k)=m=0∑N−1−kxn(m)xn(m+k)(0≤k≤K)
-
短时平均幅度差函数
乘积更难算,所以把自相关的乘改成了差
Fn(k)=m=0∑N−1−k∣xn(m)−xn(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; 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;
1000 / (locs(pks==max(pks)) / frame_size * frame_second)
|