梅尔倒谱系数(MFCC)实现
作者:随风而醒 发布时间:2022-08-08 18:28:08
标签:梅尔倒谱系数,MFCC
本文实例为大家分享了梅尔倒谱系数实现代码,供大家参考,具体内容如下
"""
@author: zoutai
@file: mymfcc.py
@time: 2018/03/26
@description:
"""
from matplotlib.colors import BoundaryNorm
import librosa
import librosa.display
import numpy
import scipy.io.wavfile
from scipy.fftpack import dct
import matplotlib.pyplot as plt
import numpy as np
# 第一步-读取音频,画出时域图(采样率-幅度)
sample_rate, signal = scipy.io.wavfile.read('OSR_us_000_0010_8k.wav') # File assumed to be in the same directory
signal = signal[0:int(3.5 * sample_rate)]
# plot the wave
time = np.arange(0,len(signal))*(1.0 / sample_rate)
# plt.plot(time,signal)
plt.xlabel("Time(s)")
plt.ylabel("Amplitude")
plt.title("Signal in the Time Domain ")
plt.grid('on')#标尺,on:有,off:无。
# 第二步-预加重
# 消除高频信号。因为高频信号往往都是相似的,
# 通过前后时间相减,就可以近乎抹去高频信号,留下低频信号。
# 原理:y(t)=x(t)−αx(t−1)
pre_emphasis = 0.97
emphasized_signal = numpy.append(signal[0], signal[1:] - pre_emphasis * signal[:-1])
time = np.arange(0,len(emphasized_signal))*(1.0 / sample_rate)
# plt.plot(time,emphasized_signal)
# plt.xlabel("Time(s)")
# plt.ylabel("Amplitude")
# plt.title("Signal in the Time Domain after Pre-Emphasis")
# plt.grid('on')#标尺,on:有,off:无。
# 第三步、取帧,用帧表示
frame_size = 0.025 # 帧长
frame_stride = 0.01 # 步长
# frame_length-一帧对应的采样数, frame_step-一个步长对应的采样数
frame_length, frame_step = frame_size * sample_rate, frame_stride * sample_rate # Convert from seconds to samples
signal_length = len(emphasized_signal) # 总的采样数
frame_length = int(round(frame_length))
frame_step = int(round(frame_step))
# 总帧数
num_frames = int(numpy.ceil(float(numpy.abs(signal_length - frame_length)) / frame_step)) # Make sure that we have at least 1 frame
pad_signal_length = num_frames * frame_step + frame_length
z = numpy.zeros((pad_signal_length - signal_length))
pad_signal = numpy.append(emphasized_signal, z) # Pad Signal to make sure that all frames have equal number of samples without truncating any samples from the original signal
# Construct an array by repeating A(200) the number of times given by reps(348).
# 这个写法太妙了。目的:用矩阵来表示帧的次数,348*200,348-总的帧数,200-每一帧的采样数
# 第一帧采样为0、1、2...200;第二帧为80、81、81...280..依次类推
indices = numpy.tile(numpy.arange(0, frame_length), (num_frames, 1)) + numpy.tile(numpy.arange(0, num_frames * frame_step, frame_step), (frame_length, 1)).T
frames = pad_signal[indices.astype(numpy.int32, copy=False)] # Copy of the array indices
# frame:348*200,横坐标348为帧数,即时间;纵坐标200为一帧的200毫秒时间,内部数值代表信号幅度
# plt.matshow(frames, cmap='hot')
# plt.colorbar()
# plt.figure()
# plt.pcolormesh(frames)
# 第四步、加汉明窗
# 傅里叶变换默认操作的时间段内前后端点是连续的,即整个时间段刚好是一个周期,
# 但是,显示却不是这样的。所以,当这种情况出现时,仍然采用FFT操作时,
# 就会将单一频率周期信号认作成多个不同的频率信号的叠加,而不是原始频率,这样就差生了频谱泄漏问题
frames *= numpy.hamming(frame_length) # 相乘,和卷积类似
# # frames *= 0.54 - 0.46 * numpy.cos((2 * numpy.pi * n) / (frame_length - 1)) # Explicit Implementation **
# plt.pcolormesh(frames)
# 第五步-傅里叶变换频谱和能量谱
# _raw_fft扫窗重叠,将348*200,扩展成348*512
NFFT = 512
mag_frames = numpy.absolute(numpy.fft.rfft(frames, NFFT)) # Magnitude of the FFT
pow_frames = ((1.0 / NFFT) * ((mag_frames) ** 2)) # Power Spectrum
# plt.pcolormesh(mag_frames)
#
# plt.pcolormesh(pow_frames)
# 第六步,Filter Banks滤波器组
# 公式:m=2595*log10(1+f/700);f=700(10^(m/2595)−1)
nfilt = 40 #窗的数目
low_freq_mel = 0
high_freq_mel = (2595 * numpy.log10(1 + (sample_rate / 2) / 700)) # Convert Hz to Mel
mel_points = numpy.linspace(low_freq_mel, high_freq_mel, nfilt + 2) # Equally spaced in Mel scale
hz_points = (700 * (10**(mel_points / 2595) - 1)) # Convert Mel to Hz
bin = numpy.floor((NFFT + 1) * hz_points / sample_rate)
fbank = numpy.zeros((nfilt, int(numpy.floor(NFFT / 2 + 1))))
for m in range(1, nfilt + 1):
f_m_minus = int(bin[m - 1]) # left
f_m = int(bin[m]) # center
f_m_plus = int(bin[m + 1]) # right
for k in range(f_m_minus, f_m):
fbank[m - 1, k] = (k - bin[m - 1]) / (bin[m] - bin[m - 1])
for k in range(f_m, f_m_plus):
fbank[m - 1, k] = (bin[m + 1] - k) / (bin[m + 1] - bin[m])
filter_banks = numpy.dot(pow_frames, fbank.T)
filter_banks = numpy.where(filter_banks == 0, numpy.finfo(float).eps, filter_banks) # Numerical Stability
filter_banks = 20 * numpy.log10(filter_banks) # dB;348*26
# plt.subplot(111)
# plt.pcolormesh(filter_banks.T)
# plt.grid('on')
# plt.ylabel('Frequency [Hz]')
# plt.xlabel('Time [sec]')
# plt.show()
#
# 第七步,梅尔频谱倒谱系数-MFCCs
num_ceps = 12 #取12个系数
cep_lifter=22 #倒谱的升个数??
mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1 : (num_ceps + 1)] # Keep 2-13
(nframes, ncoeff) = mfcc.shape
n = numpy.arange(ncoeff)
lift = 1 + (cep_lifter / 2) * numpy.sin(numpy.pi * n / cep_lifter)
mfcc *= lift #*
# plt.pcolormesh(mfcc.T)
# plt.ylabel('Frequency [Hz]')
# plt.xlabel('Time [sec]')
# 第八步,均值化优化
# to balance the spectrum and improve the Signal-to-Noise (SNR), we can simply subtract the mean of each coefficient from all frames.
filter_banks -= (numpy.mean(filter_banks, axis=0) + 1e-8)
mfcc -= (numpy.mean(mfcc, axis=0) + 1e-8)
# plt.subplot(111)
# plt.pcolormesh(mfcc.T)
# plt.ylabel('Frequency [Hz]')
# plt.xlabel('Time [sec]')
# plt.show()
# 直接频谱分析
# plot the wave
# plt.specgram(signal,Fs = sample_rate, scale_by_freq = True, sides = 'default')
# plt.ylabel('Frequency(Hz)')
# plt.xlabel('Time(s)')
# plt.show()
plt.figure(figsize=(10, 4))
mfccs = librosa.feature.melspectrogram(signal,sr=8000,n_fft=512,n_mels=40)
librosa.display.specshow(mfccs, x_axis='time')
plt.colorbar()
plt.title('MFCC')
plt.tight_layout()
plt.show()
来源:https://blog.csdn.net/SoundSlow/article/details/79711227


猜你喜欢
- 下载MySQL-8.0.23点击下载:mysql-8.0.23-linux-glibc2.12-x86_64.tar.xz解压MySQL的安
- 很多时候,设计师们都会通过各种渠道去了解用户的需求,然而从这些渠道反馈回来的信息大部分只是用户的期望并不是真正的用户需求,但是很多时候这些期
- 1.Access数据库的DSN-less连接方法: set adocon=Server.Createobject(&q
- 本文实例为大家分享了pytorch实现线性回归以及多元回归的具体代码,供大家参考,具体内容如下最近在学习pytorch,现在把学习的代码放在
- 格式getopt(args, options[, long_options])1.args表示要解析的参数. 2.options表示脚本要识
- 一、分块查找算法分块查找是二分法查找和顺序查找的改进方法,分块查找要求索引表是有序的,对块内结点没有排序要求,块内结点可以是有序的也可以是无
- 平时工作过程中,git在push代码的时候有时会遇到如下的错误错误原因文件冲突,本地的代码和远程Repository中的文件个数不一致(即远
- 在平时,常常会提醒自己要做一个善于发现的人,时刻发现细节,这样才会更加懂得生活、会让生活更加精彩。在学习上也是如此,我们常常会发现有很多网站
- 1、获取元素 2、获取数据 3、绑定数据 4、隔行换色&
- 从一个字符串开始在CODE上查看代码片派生到我的代码片 >>>time_str='2008-08-08
- 本文介绍了vue生成随机验证码的示例代码,分享给大家,具体如下:样式自调,最终效果如图:实现效果:点击右边input框会自动切换,如果输入的
- vue时间格式转化问题1. 效果图2. 需求:前台展示一律用的时间规格yyyy-MM-dd HH:mm:SS,即要求月日
- JavaScript lastIndexOf 方法lastIndexOf 方法用于计算指定的字符串在整个字符串中最后一次出现的位置,并返回该
- 1. 错误提示 Warning: Cannot send session cookie - headers already sent War
- css的流行导致了标签的流行,很直观,看起来很清爽。流行的一部分,还有很多种功能强大且美观的导航。。。1. Change.org2. N.D
- python函数一、函数定义函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。你
- for...[if]...构建List (List comprehension)1.简单的for...[if]...语句Python中,fo
- 在ASP中,如何创建DSN? 见下:<HTML><HEAD><META&n
- 前文复习:openCV第一篇openCV第二篇一、Canny边缘检测该边缘检测法步骤如下:使用高斯滤波器,以平滑图像,滤除噪声。计算图像中每
- 本文实例讲述了Python正则表达式实现截取成对括号的方法。分享给大家供大家参考,具体如下:strs = '1(2(3(4(5(67