语音特征提取:从预处理到声学特征
语音特征提取是语音处理和识别的关键步骤,它涉及从原始语音信号中提取有用的信息,以便于后续的分析和处理。本文将详细介绍语音特征提取的各个步骤,包括预处理、短时傅里叶变换、听觉特性、线性预测、倒谱分析以及常用的声学特征。本文旨在为入门级小白提供一个详细的教程,帮助理解语音特征提取的基本概念和方法。
文章目录
- 语音特征提取:从预处理到声学特征
- 3.1 预处理
- 去噪
- 分帧
- 加窗
- 预处理示例代码(Python)
- 3.2 短时傅里叶变换
- STFT示例代码(Python)
- 3.3 听觉特性
- 3.4 线性预测
- LPC示例代码(Python)
- 3.5 倒谱分析
- MFCC示例代码(Python)
- 3.6 常用的声学特征
- 3.6.1 语谱图
- 语谱图示例代码(Python)
- 3.6.2 FBank
- FBank示例代码(Python)
- 3.6.3 MFCC
- MFCC示例代码(Python)
- 3.6.4 PLP
- PLP示例代码(Python)
- 3.7 本章小结
3.1 预处理
预处理是语音特征提取的第一步,其目的是去除信号中的噪声和不必要的成分,以便于后续处理。预处理通常包括以下几个步骤:
去噪
去噪是通过使用滤波器去除信号中的高频噪声和低频干扰。例如,可以使用低通滤波器去除高频噪声,使用高通滤波器去除低频干扰。
import numpy as np
from scipy.signal import butter, lfilterdef butter_lowpass(cutoff, fs, order=5):nyq = 0.5 * fsnormal_cutoff = cutoff / nyqb, a = butter(order, normal_cutoff, btype='low', analog=False)return b, adef butter_lowpass_filter(data, cutoff, fs, order=5):b, a = butter_lowpass(cutoff, fs, order=order)y = lfilter(b, a, data)return y# 示例:对信号应用低通滤波器
cutoff = 4000 # 低通滤波器的截止频率
sample_rate = 16000 # 假设采样率为16kHz
signal = butter_lowpass_filter(signal, cutoff, sample_rate)
分帧
分帧是将连续的语音信号分割成短时帧,每帧通常为20-40毫秒。分帧的目的是利用语音信号的短时平稳性,使得每一帧可以被认为是平稳的,从而便于后续的频谱分析。
frame_size = 0.025 # 帧长25毫秒
frame_stride = 0.01 # 帧移10毫秒
frame_length, frame_step = frame_size * sample_rate, frame_stride * sample_rate
signal_length = len(signal)
frame_length = int(round(frame_length))
frame_step = int(round(frame_step))
num_frames = int(np.ceil(float(np.abs(signal_length - frame_length)) / frame_step))pad_signal_length = num_frames * frame_step + frame_length
z = np.zeros((pad_signal_length - signal_length))
pad_signal = np.append(signal, z)indices = np.tile(np.arange(0, frame_length), (num_frames, 1)) + np.tile(np.arange(0, num_frames * frame_step, frame_step), (frame_length, 1)).T
frames = pad_signal[indices.astype(np.int32, copy=False)]
加窗
对每一帧信号应用窗函数(如汉明窗),以减少频谱泄漏。加窗的目的是减少帧之间的边界效应,从而提高频谱分析的精度。常用的窗函数有矩形窗、汉明窗、汉宁窗等。
frames *= np.hamming(frame_length)
预处理示例代码(Python)
import numpy as np
import scipy.io.wavfile as wav# 读取语音信号
sample_rate, signal = wav.read('path_to_your_audio_file.wav')# 去噪(简单示例:使用低通滤波器)
from scipy.signal import butter, lfilterdef butter_lowpass(cutoff, fs, order=5):nyq = 0.5 * fsnormal_cutoff = cutoff / nyqb, a = butter(order, normal_cutoff, btype='low', analog=False)return b, adef butter_lowpass_filter(data, cutoff, fs, order=5):b, a = butter_lowpass(cutoff, fs, order=order)y = lfilter(b, a, data)return ycutoff = 4000 # 低通滤波器的截止频率
signal = butter_lowpass_filter(signal, cutoff, sample_rate)# 分帧
frame_size = 0.025 # 帧长25毫秒
frame_stride = 0.01 # 帧移10毫秒
frame_length, frame_step = frame_size * sample_rate, frame_stride * sample_rate
signal_length = len(signal)
frame_length = int(round(frame_length))
frame_step = int(round(frame_step))
num_frames = int(np.ceil(float(np.abs(signal_length - frame_length)) / frame_step))pad_signal_length = num_frames * frame_step + frame_length
z = np.zeros((pad_signal_length - signal_length))
pad_signal = np.append(signal, z)indices = np.tile(np.arange(0, frame_length), (num_frames, 1)) + np.tile(np.arange(0, num_frames * frame_step, frame_step), (frame_length, 1)).T
frames = pad_signal[indices.astype(np.int32, copy=False)]# 加窗
frames *= np.hamming(frame_length)
3.2 短时傅里叶变换
短时傅里叶变换(Short-Time Fourier Transform, STFT)是分析语音信号频谱的一种常用方法。它通过在时间轴上滑动一个固定长度的窗口,对每一帧信号进行傅里叶变换,从而得到信号的时频表示。STFT的结果是一个复数矩阵,表示信号在不同时间和频率上的能量分布。
STFT示例代码(Python)
from scipy.fftpack import fft# 计算STFT
NFFT = 512 # FFT的点数
mag_frames = np.abs(np.fft.rfft(frames, NFFT)) # 计算每一帧的FFT
pow_frames = ((1.0 / NFFT) * ((mag_frames) ** 2)) # 计算功率谱
3.3 听觉特性
人类的听觉系统对声音的感知具有特定的特性,这些特性可以被用来设计更符合人类听觉的特征提取方法。听觉特性包括:
-
频率选择性:人耳对不同频率的声音敏感度不同,通常对中频声音最敏感。
-
临界带宽:人耳对频率的分辨能力在不同频段是不同的。临界带宽是指人耳能够区分的最小频率间隔,低频段的临界带宽较窄,高频段的临界带宽较宽。
-
响度感知:人耳对声音的响度感知是非线性的。相同的声压级在不同频率下感知的响度不同,这种现象通过等响度曲线描述。
3.4 线性预测
线性预测(Linear Prediction, LP)是一种基于信号模型的特征提取方法。它假设语音信号可以由过去的样本线性组合预测得到。线性预测系数(Linear Prediction Coefficients, LPC)可以用来表示语音信号的声道特性。
LPC示例代码(Python)
from scipy.signal import lfilterdef lpc(signal, order):"""Compute LPC coefficients."""n = len(signal)r = np.correlate(signal, signal, mode='full')r = r[n-1:]a = np.zeros((order + 1,))a[0] = 1.0k = np.zeros((order + 1,))e = r[0]for i in range(1, order + 1):k[i] = np.sum(a[:i] * r[i:0:-1]) / ea[1:i+1] = a[1:i+1] - k[i] * a[i-1::-1]e = e * (1 - k[i]**2)return a# 计算LPC系数
order = 12 # LPC的阶数
lpc_coeffs = lpc(frames[0], order)
3.5 倒谱分析
倒谱分析(Cepstral Analysis)是一种将信号的频谱进行对数运算后再进行傅里叶变换的方法。倒谱分析可以分离信号的声道特性和激励源特性。最常用的倒谱特征是梅尔频率倒谱系数(Mel-Frequency Cepstral Coefficients, MFCC)。
MFCC示例代码(Python)
from python_speech_features import mfcc# 计算MFCC
num_ceps = 12 # MFCC的系数数量
mfcc_features = mfcc(signal, samplerate=sample_rate, numcep=num_ceps, nfilt=26, nfft=512)
3.6 常用的声学特征
3.6.1 语谱图
语谱图(Spectrogram)是STFT结果的视觉表示,它显示了信号在时间和频率上的能量分布。语谱图通常使用灰度图表示,其中颜色深浅表示能量大小。
语谱图示例代码(Python)
import matplotlib.pyplot as plt# 绘制语谱图
plt.specgram(signal, NFFT=512, Fs=sample_rate)
plt.xlabel('Time')
plt.ylabel('Frequency')
plt.show()
3.6.2 FBank
滤波器组特征(Filter Bank, FBank)是一种基于听觉特性的特征提取方法。它通过一组带通滤波器对信号的频谱进行滤波,得到一组能量值,这些能量值可以反映信号在不同频段的能量分布。
FBank示例代码(Python)
from python_speech_features import logfbank# 计算FBank特征
fbank_features = logfbank(signal, samplerate=sample_rate, nfilt=26, nfft=512)
3.6.3 MFCC
梅尔频率倒谱系数(MFCC)是一种广泛使用的声学特征,它结合了梅尔刻度和倒谱分析的优点。MFCC的提取过程包括:信号预处理、STFT、梅尔滤波器组滤波、对数运算和离散余弦变换(DCT)。
MFCC示例代码(Python)
from python_speech_features import mfcc# 计算MFCC
num_ceps = 12 # MFCC的系数数量
mfcc_features = mfcc(signal, samplerate=sample_rate, numcep=num_ceps, nfilt=26, nfft=512)
3.6.4 PLP
感知线性预测(Perceptual Linear Prediction, PLP)是一种结合了听觉模型和线性预测的特征提取方法。PLP特征提取过程包括:信号预处理、STFT、巴克刻度滤波、对数运算、逆离散傅里叶变换(IDFT)和线性预测分析。
PLP示例代码(Python)
from python_speech_features import pLPCC# 计算PLP特征
plp_features = pLPCC(signal, samplerate=sample_rate, numcep=12, nfilt=26, nfft=512)
3.7 本章小结
语音特征提取是一个多步骤的过程,涉及信号的预处理、频谱分析、听觉模型应用、信号建模和特征转换。不同的特征提取方法各有优缺点,选择合适的特征对于提高语音识别系统的性能至关重要。通过本文的介绍,希望读者能够对语音特征提取有一个全面的理解,并能够在实际应用中选择和设计合适的特征提取方法。