需要库:
- numpy
- librosa
- scipy
- matplotlib
在分析之前,先将音频导入一个变量内提供观察。 其中的音频文件song070_f00005j_063.wav
来自Sinsy.jp 的 f00005j
音源合成。
import librosa
y, sr = librosa.load('song070_f00005j_063.wav', sr=None) # Librosa默认的采样率是22050,如果需要读取原始采样率,需要设定参数sr=None
可以将波形的数组打印出来
print(y)
---
[0.0000000e+00 0.0000000e+00 0.0000000e+00 ... 2.9368461e-05 3.1804815e-05
0.0000000e+00]
其中sr是音频的采样率,一般有11025Hz、22050Hz、24000Hz、44100Hz、48000Hz这几种
print(sr)
---
48000
语音信号的分析方法不过这两种:
- 时域法
- 频域法
时域法
时域法的处理对象是一维的波形 对应的方法如下:
import librosa.display
from matplotlib import pyplot as plt
librosa.display.waveplot(y, sr)
plt.show()
从图中可以看出音频的时长,音节的位置,区分浊音轻音 但是时域法最大的问题是没有直观的显示
频域法
我们通常认为语音信号的频谱是时变的,所以可以用一个STFT变换进行分析,它的定义为:
\[X_{n}\left(\mathrm{e}^{j \omega}\right)=\sum_{m=-\infty}^{+\infty} x(m) w(n-m) \mathrm{e}^{-j \omega m}\]从式中可以看到: 短时傅里叶变换有两个自变量($n$和$ω$);所以它既是关于时间n的离散函数;又是关于角频率$ω$的连续函数。式中;$w(n)$是窗函数;$n$取不同值时;取出不同的语音短段;这里用下标n区别于标准的傅里叶变换。由于窗的形状对短时谱有影响,故窗函数应具备如下特性:
- 频率分辨率高,即主瓣狭窄、尖锐;
- 旁瓣衰减较大,在其他频率成分产生的频谱泄露少。这两个条件其实是相互矛盾的,不可能同时满足,因此,我们经常采取折中的处理办法,多选择汉明窗($hamming$)窗。
频域分析法是应用频率特性研究线性系统的一种图解方法。频率特性和传递函数一样,可以用来表示线性系统或环节的动态特性。建立在频率特性基础上的分析控制系统的频域法弥补了时域分析法中的不足,因而获得了广泛的应用。所谓频率特性是系统的频率响应与正弦输入信号的复数比。而频率响应是指系统在正弦输入信号作用下,线性系统输出的稳态分量。频域分析法的优势主要体现在:
- 频率特性虽然是一种稳态特性,但它不仅仅反映系统的稳态性能,还可以用来研究系统的稳定性和瞬态性能,而且不必解出特征方程的根。
- 频率特性与二阶系统的过渡过程性能指标有着确定的对应关系,从而可以较方便地分析系统中参量对系统瞬态响应的影响。
- 线性系统的频率特性可以非常容易地由解析法得到。
- 许多元件和稳定系统的频率特性都可用实验的方法来测定,这对于很难从分析其物理规律着手来列写动态方程的元件和系统来说,具有特别重要的意义。
- 频域分析法不仅适用于线性系统,也可以推广到某些非线性系统的分析研究中。
然而,时域分析和频域分析都有各自的局限性:时域分析对语音信号的频率特性没有直观的显示;频域分析中又缺乏语音信号随时间的变化关系。于是,人们采用语谱分析的法分析语音信号,语谱分析描述的是动态的频谱,反映了语音频谱随时间的变化情况,它综合了时域分析和频域分析的优点。语谱图是语谱分析的外在表现形式,语谱图也称频谱分析视图,采用二维平面来表示三维信息。它的横坐标是时间,纵坐标是频率,坐标点值为语音数据能量。由于是采用二维平面表达三维信息,所以能量值的大小是通过颜色来表示的,颜色深,表示该点的语音能量越强。
绘制的方法:
- 提取Log-Mel Spectrogram 特征
Log-Mel Spectrogram特征是目前在语音识别和环境声音识别中很常用的一个特征,由于CNN在处理图像上展现了强大的能力,使得音频信号的频谱图特征的使用愈加广泛,甚至比MFCC使用的更多。 Log-Mel Spectrogram特征是二维数组的形式,128表示Mel频率的维度(频域),1637为时间帧长度(时域),所以Log-Mel Spectrogram特征是音频信号的时频表示特征。其中,n_fft指的是窗的大小,这里为1024;hop_length表示相邻窗之间的距离,这里为512,也就是相邻窗之间有50%的overlap;n_mels为mel bands的数量,这里设为128。
melspec = librosa.feature.melspectrogram(y, sr, n_fft=1024, hop_length=512, n_mels=128)
logmelspec = librosa.power_to_db(melspec)
librosa.display.specshow(logmelspec, sr=sr, x_axis='time', y_axis='mel')
print(logmelspec.shape)
plt.show()
---
(128, 1637)