numcpp速度对比_librosa库log-mel,pcen特征提取(C++移植)mfcc

本文对比了使用C++库numcpp和Python的librosa库在log-mel及pcen特征提取上的速度。在Python中,librosa实现耗时约200ms(不计文件加载),而C++实现(使用NumCpp和优化后的FFT)首次运行耗时11ms,后续运行7ms。文章详细介绍了C++代码的移植过程,包括使用NumCpp和OpenCV进行矩阵运算,并优化了FFT和IIR滤波器的效率。
摘要由CSDN通过智能技术生成

一、介绍

为什么要使用mel特征提取?

因为音频数据如果直接拿来做自动语音识别会效果非常差,由于音频存在很多噪音,并且音频中我们需要的有效数据并没有被凸显出来,而使用mel特征提取可以将音频数据里有效信息进行提取、无用信息进行过滤,其原理是模拟人耳构造,对音频进行滤波,处理过后的数据再用来做自动语音识别效果会有显著提升。

librosa库:

librosa.filters.mel:https://librosa.github.io/librosa/generated/librosa.filters.mel.html

librosa.core.pcen:https://librosa.github.io/librosa/generated/librosa.core.pcen.html

pcen论文《Trainable Frontend For Robust and Far-Field Keyword Spotting》:https://arxiv.org/pdf/1607.05666.pdf

1.概念

Mel频率倒谱系数(Mel Frequency Cepstrum Coefficient)的缩写是MFCC,是一种在自动语音和说话人识别中广泛使用的特征。

Mel频率是基于人耳听觉特性提出来的,它与Hz频率成非线性对应关系。Mel频率倒谱系数(MFCC)则是利用它们之间的这种关系,计算得到的Hz频谱特征。

用录音设备录制一段模拟语音信号后,经由自定的取样频率(如8000 Hz、16000 Hz等)采样后转换(A/D)为数字语音信号。由于在时域(time domain)上语音信号的波形变化相当快速、不易观察,因此一般都会在频域(frequency domain)上来观察,其频谱是随着时间而缓慢变化的,因此通常可以假设在一较短时间中,其语音信号的特性是稳定的,通常我们定义这个较短时间为一帧(frame),根据人的语音的音调周期值的变化,一般取10~20ms。

关于概念,请查阅:https://www.e-learn.cn/content/qita/798278

开始前还请熟悉运算流程:https://blog.csdn.net/zouxy09/article/details/9156785

关于教程,请查阅:http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/

任何自动语音识别系统的第一步是提取特征,即识别音频信号的组成部分,这些组成部分有助于识别语言内容并丢弃所有其他携带诸如背景噪声,情绪等信息的东西。

理解语音的要点是人类产生的声音被声道的形状过滤,包括舌头,牙齿等。这种形状决定了声音的出现。如果我们能够准确地确定形状,这应该能够准确地表示正在生产的音素。声道的形状表现在短时功率谱的包络中,MFCC的工作是准确地表示这个包络。本页面将提供有关MFCC的简短教程。

Mel频率倒谱系数(MFCC)是一种广泛用于自动语音和说话人识别的功能。它们是戴维斯和梅尔斯坦在20世纪80年代引入的,从那以后一直是最先进的。在引入MFCC之前,线性预测系数(LPC)和线性预测倒谱系数(LPCC)(点击此处获取关于倒谱和LPCC的教程)并且是自动语音识别(ASR)的主要特征类型,特别是对于HMM分类器。本页将介绍MFCC的主要方面,为什么它们为ASR提供了一个很好的功能,以及如何实现它们。

2.步骤一览

我们将对实施步骤进行高级介绍,然后深入探讨为什么我们要做的事情。接下来,我们将详细介绍如何计算MFCC。

1.将信号帧化为短帧。

2.对于每个帧,计算功率谱的周期图估计。

3.将mel滤波器组应用于功率谱,将每个滤波器中的能量相加。

4.取所有滤波器组能量的对数。

5.获取日志滤波器组能量的DCT。

6.保持DCT系数2-13,丢弃其余部分。

二、python实现

基于:Ubuntu 16.04LTS,Core-i7 8700,PyCharm

对于一个2秒22050采样率的文件:

总体耗时:约200ms

除开文件加载耗时:9ms

基于librosa:

# sr = 22050 # Sample rate.

sr = 16000 # 16000 # keda, thchs30, aishell

n_fft = 2048 # fft points (samples)

frame_shift = 0.05 # seconds

frame_length = 0.1 # seconds

hop_length = int(sr * frame_shift) # samples.

win_length = int(sr * frame_length) # samples.

n_mels = 80 # Number of Mel banks to generate

power = 1.2 # Exponent for amplifying the predicted magnitude

n_iter = 50 # Number of inversion iterations

preemphasis = .97 # or None

max_db = 100

ref_db = 20

# log-mel特征提取

def get_spectrograms(fpath, use_path=True):

'''Returns normalized log(melspectrogram) and log(magnitude) from `sound_file`.

Args:

sound_file: A string. The full path of a sound file.

Returns:

mel: A 2d array of shape (T, n_mels)

# Loading sound file

if use_path:

y, sr = librosa.load(fpath, sr=hp.sr)

# with open("x.bin", 'wb') as fp:

# for i in range(len(y)):

# print("y[", i, "]: ", y[i])

# bs = struct.pack("f", y[i])

# # a = struct.pack('B', i)

# fp.write(bs)

else:

y, sr = fpath, hp.sr

print("y.shape: ", y.shape)

print("sr: ", sr)

time1 = time.time()

# Trimming

# y, _ = librosa.effects.trim(y)

# Preemphasis pre-emphasis,预加重

y = np.append(y[0], y[1:] - hp.preemphasis * y[:-1])

# stftz

linear = librosa.stft(y=y,

n_fft=hp.n_fft,

hop_length=hp.hop_length,

win_length=hp.win_length)

# magnitude spectrogram

mag = np.abs(linear) # (1+n_fft//2, T)

# mel spectrogram

mel_basis = librosa.filters.mel(hp.sr, hp.n_fft, hp.n_mels) # (n_mels, 1+n_fft//2)

mel = np.dot(mel_basis, mag) # (n_mels, t)

# to decibel

mel = 20 * np.log10(np.maximum(1e-5, mel))

mag = 20 * np.log10(np.maximum(1e-5, mag))

# normalize

mel = np.clip((mel - hp.ref_db + hp.max_db) / hp.max_db, 1e-8, 1)

mag = np.clip((mag - hp.ref_db + hp.max_db) / hp.max_db, 1e-8, 1)

# Transpose

mel = mel.T.astype(np.float32) # (T, n_mels)

mag = mag.T.astype(np.float32) # (T, 1+n_fft//2)

#

mel = mel[:len(mel) // hp.r * hp.r].reshape([len(mel) // hp.r, hp.r * hp.n_mels])

mag = mag[:len(mag) // hp.r * hp.r] # .reshape([len(mag)//hp.r,hp.r*1025])

time2 = time.time()

print("cost time:", time2-time1)

return mel, mag

# pcen-mel特征提取

def get_pcen(fpath, use_path=True):

# Loading sound file

if use_pat

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值