当前所在位置: 首页 > 资讯

每日简讯:语音处理加窗分帧

2023-04-28 12:28:00来源:博客园
语音处理加窗分帧一、分帧

语音数据和视频数据不同,本没有帧的概念,但是为了传输与存储,我们采集的音频数据都是一段一段的。为了程序能够进行批量处理,会根据指定的长度(时间段或者采样数)进行分段,结构化为我们编程的数据结构,这就是分帧。

二、帧移

由于我们常用的信号处理方法都要求信号是连续的,也就说必须是信号开始到结束,中间不能有断开。然而我们进行采样或者分帧后数据都断开了,所以要在帧与帧之间保留重叠部分数据,以满足连续的要求,这部分重叠数据就是帧移。


(资料图片)

三、加窗

介绍帧移的时候我们说了,我们处理信号的方法都要求信号是连续条件,但是分帧处理的时候中间断开了,为了满足条件我们就将分好的帧数据乘一段同长度的数据,这段数据就是窗函数整个周期内的数据,从最小变化到最大,然后最小。

四、滤波

我们知道,我们处理的语音其实是一种声波,声波是一种物质波。滤波的字面意思理解为过滤一些不同频率的波。根据傅里叶变换,我们知道任意波可以分解为几种正弦波和余弦波的叠加,从概率论的角度,滤波即加权。 滤波的作用就是给不同的信号分量不同的权重。最简单的loss pass filter, 就是直接把低频的信号给0权重,而给高频部分1权重。对于更复杂的滤波,比如维纳滤波, 则要根据信号的统计知识来设计权重。

当允许信号中较高频率的成分通过滤波器时,这种滤波器叫做高通滤波器。当允许信号中较低频率的成分通过滤波器时,这种滤波器叫做低通滤波器。当只允许信号中某个频率范围内的成分通过滤波器时,这种滤波器叫做带通滤波器。当不允许信号中某个频率范围内的成分通过滤波器时,这种滤波器叫做带阻滤波器。

五、降噪

从统计信号处理的角度,降噪可以看成滤波的一种。降噪的目的在于突出信号本身而抑制噪声影响。从这个角度,降噪就是给信号一个高的权重而给噪声一个低的权重。维纳滤波就是一个典型的降噪滤波器。

六、合成

在语音处理过程,先分帧,再在频域分成各个子带处理,处理后转成时域,合成语声。从描述上看,语音合成就是和分帧相反的过程,保证信号数据经过我们变换处理后能够回到原来的状态。把每帧各个子带转换成时间序列后相互叠加合成为一帧数据。

七、具体理解1、为什么要进行分帧加窗操作?

语音信号为非平稳信号,其统计属性是随着时间变化的,以汉语为例,一句话中包含很多生母和韵母,不同的拼音,发音的特点很明显是不一样的;但是,语音又具有平稳的属性,比如汉语里的一个声母或者韵母,往往只会持续几十到几百毫秒,这一个发音单元里,语音信号表现出明显的稳定性、规律性,在进行语音识别时,对于一句话识别的过程也是以较小的发音单元(音素、字、字节)为单位进行识别的,因此可以用滑动窗来提取短时片段,也即进行分帧加窗操作。

2、如何进行分帧加窗操作?2.1 相关术语

帧长:一帧语音信号的长度,长度可以用多种方式表示,如果用时间表示,一帧信号通常取在15ms-30ms之间,经验值为25ms(论文上大多数人用)。帧长为25ms的一帧信号指的是时长有25毫秒的语音信号。也可以用信号的采样点数来表示,如果一个信号的采样率为16kHz,则一帧信号由 16kHz * 25ms = 400个采样点组成。

帧移:指的是每次分帧时移动的距离,以第一帧信号的起始点开始移动一个帧移,开始下一帧。同样也可以用两种方式表示,用时间表示,常设为10ms,用采样点表示,16kHz采样率的信号帧移一般为160个采样点。

加窗:分帧后每一帧的开始和结束都会出现间断,因此分割的帧越多,与原始信号的误差就越大,加窗就是为了解决这个问题,使成帧后的信号变得连续,并且每一帧都会表现出周期函数的特性。常见的窗函数有:矩形窗、汉明窗、汉宁窗等,在语音信号处理中,通常使用汉明窗,其公式如下:

2.2 分帧加窗的具体操作

首先要根据信号长度、帧移、帧长计算出该信号一共可以分的帧数,帧数的计算公式如下:帧数 = (信号长度-帧长)➗帧移 +1具体的分帧操作如下图所示:

加窗操作比较简单,仅需将分帧的每一帧信号一次与窗函数进行相乘即可,其中窗函数可以从numpy里直接调用。在分帧操作时,会遇到最后剩下的信号长度不够一帧的情况,此时需要将对这一段信号进行补零操作,使之达到一帧的长度,或者可以直接将之抛弃,因为最后一帧处于句子最末尾部分,大部分为静音片段。

3 分帧加窗的代码实现

以下是实现分帧加窗的具体代码:

def enframe(signal, frame_len=frame_len, frame_shift=frame_shift, win=np.hamming(frame_len)):    """    calculate the number of frames:     frames = (num_samples -frame_len) / frame_shift +1    """    num_samples = signal.size    num_frames = np.floor((num_samples - frame_len) / frame_shift)+1      # calculate the numbers of frames    frames = np.zeros((int(num_frames),frame_len))   # (num_frames,frame_len)    # Initialize an array for putting the frame signals into it    for i in range(int(num_frames)):        frames[i,:] = signal[i*frame_shift:i*frame_shift + frame_len]        frames[i,:] = frames[i,:] * win    return frames

其中需要注意以下几点:

①signal代表经过预加重后的信号,frame_len为帧长,frame_shift为帧移。②np.hamming(frame_len)实现了汉明窗函数。③上面的代码中,如果计算出信号长为5.2帧,则取为5帧,因为最后一帧一般都是静音信号,可以省略。初始化一个存放帧信号的数组frames,然后依次将- signal信号里的数据按照分帧操作赋值给frames。④如果输入信号的采样率为16kHz,帧长为400个采样点,帧移为160个采样点,则经过分帧加窗后得到的数组的形状为(帧数行,帧长列)。

关键词:

上一篇:指尖上的梦徽州工匠记
下一篇:最后一页