spec = librosa.feature.melspectrogram(sig,n_fft=2048,hop_length=256,window="hann")
如同前面文章所讲的,真正在取 spectrogram 的时候呢,并不是单纯的只做 STFT ,在做 STFT 之前还会有一些操作,通常是这三个:
Step1. 预强调(Pre-emphasis)将语音信号 s(n) 通过一个高通滤波器
H(z) = 1−a∗z−1 where 0.9 < a < 1.0
若以时域的运算式来表示,预强调后的信号 s2(n) 就是
s2(n) = s(n)−a∗s(n−1)
这样处理是为了消除发声过程中声带和嘴唇的效应,来补偿语音信号受到发音系统所压抑的高频部分。也有另一种说法是说要突显在高频的共振峰。
Step 2. 音框化(Frame Blocking)将 N 个取样点集合成一个观测单位,称为音框(Frame),通常 N 的值是 256 或 512,涵盖的时间约 20~30 ms。
为了避免相邻两音框的变化过大,会让两相邻音框之间有一段重迭区域,此重迭区域包含了 M 个取样点,通常 M 的值是 N 的一半或 1/3。
假设所用的音讯的 sample rate 为 16 KHz 且音框长度为 256 ,对应的时间长度就是 256/16000*1000 = 16 ms。
n_fft 指的就是这个 N 值,默认是 2048,对应的 sample rate 是 22.05 KHz,是最适合处理音乐信号的
Step3. 乘上窗涵式(window)窗函数是一种除在给定区间之外取值均为 0 的实函数,任何函数与窗函数的乘积还是一个窗函数,
把每一个音框乘上窗涵式(汉明窗,三角窗 …etc),就可以增加音框左端和右端的连续性,保持连续性的主要原因是因为在进行 FFT 时,都是假设一个音框内的信号是代表一个周期性信号,如果这个周期性不存在,FFT 会为了要符合左右端不连续的变化,而产生一些不存在原信号的能量分布,造成分析上的误差。
如果在取音框时,已经确定音框中的信号包含了基本周期的整数倍,这时的音框左右端会是连续的,就可以不用乘窗涵式了。但在实例化上基本周期的计算会需要额外的时间,而且容易算错,因此都用窗涵式来达到类似的效果。
我们假设音框化的信号为 S(n)
S(n), n=0,…N−1。 乘上 Hanning 窗 W(n) (n) = S(n)∗W(n)
其中 W(n) 形式如下:
所以 window="hann" 的意思就是使用 "Hanning" 这个窗涵式,你也可以用其他窗涵式,再做完以上三步之后才会进行 STFT。
而 hop_lenght 指的就是 STFT 的音频样本量,默认值是 win_length // 4,加窗之后的窗口长度,默认是等於 n_fft 的长度,假设现在的窗口长度是 256, hop_lenght 是 250,那出来的结果就会变成两个,因为从 251 开始又被视为新的一帧。
下面是一个简单的实验,其中 sig 的长度为 2047
最后我们得到的结论是 librosa.stft 的输出帧数为
(sig_length // hop_length) + 1
原链接:https://www.joysns.com/article/E753B6577A68F214FE09333258EE2D39