STFT和声谱图,梅尔频谱(Mel Bank Features)与梅尔倒谱(MFCCs)

最近小编在做ASC(Acoustic Scene Classification)问题,不管是用传统的GMM模型,还是用机器学习中的SVM或神经网络模型,提取声音特征都是第一步。梅尔频谱和梅尔倒谱就是使用非常广泛的声音特征形式,小编与它们斗争已有一段时间了,在此总结一下使用它们的经验。

STFT和声谱图(Spectrogram)

声音信号本是一维的时域信号,直观上很难看出频率变化规律。如果通过傅里叶变换把它变到频域上,虽然可以看出信号的频率分布,但是丢失了时域信息,无法看出频率分布随时间的变化。为了解决这个问题,很多时频分析手段应运而生。短时傅里叶,小波,Wigner分布等都是常用的时频域分析方法。

短时傅里叶变换(STFT)是最经典的时频域分析方法。傅里叶变换(FT)想必大家都不陌生,这里不做专门介绍。所谓短时傅里叶变换,顾名思义,是对短时的信号做傅里叶变化。那么短时的信号怎么得到的? 是长时的信号分帧得来的。这么一想,STFT的原理非常简单,把一段长信号分帧、加窗,再对每一帧做傅里叶变换(FFT),最后把每一帧的结果沿另一个维度堆叠起来,得到类似于一幅图的二维信号形式。如果我们原始信号是声音信号,那么通过STFT展开得到的二维信号就是所谓的声谱图。
声谱图示意图

有很多工具方便地支持STFT展开,如果你是和小编一样是python爱好者,可以使用scipy库中的signal模块。如果你想做STFT分解的音频信号(wav文件)的路径存在path变量中,可通过下面的代码得到STFT数据。

import wavio
import numpy as np
from scipy import signal

wav_struct=wavio.read(path)
wav=wav_struct.data.astype(float)/np.power(2,wav_struct.sampwidth*8-1)
[f,t,X]=signal.spectral.spectrogram(wav,np.hamming(1024),nperseg=1024,noverlap=0,detrend=False,return_onesided=True,mode='magnitude')

 
 

    关于signal模块中spectrogram的使用方法和各个参数的具体意义,参见https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html#scipy.signal.spectrogram

    梅尔频谱和梅尔倒谱

    声谱图往往是很大的一张图,为了得到合适大小的声音特征,往往把它通过梅尔标度滤波器组(mel-scale filter banks),变换为梅尔频谱。什么是梅尔滤波器组呢?这里要从梅尔标度(mel scale)说起。

    梅尔标度,the mel scale,由Stevens,Volkmann和Newman在1937年命名。我们知道,频率的单位是赫兹(Hz),人耳能听到的频率范围是20-20000Hz,但人耳对Hz这种标度单位并不是线性感知关系。例如如果我们适应了1000Hz的音调,如果把音调频率提高到2000Hz,我们的耳朵只能觉察到频率提高了一点点,根本察觉不到频率提高了一倍。如果将普通的频率标度转化为梅尔频率标度,映射关系如下式所示:
    这里写图片描述
    图一
    则人耳对频率的感知度就成了线性关系。也就是说,在梅尔标度下,如果两段语音的梅尔频率相差两倍,则人耳可以感知到的音调大概也相差两倍。
    让我们观察一下从Hz到mel的映射图,由于它们是log的关系,当频率较小时,mel随Hz变化较快;当频率很大时,mel的上升很缓慢,曲线的斜率很小。这说明了人耳对低频音调的感知较灵敏,在高频时人耳是很迟钝的,梅尔标度滤波器组启发于此。
    这里写图片描述
    如上图所示,40个三角滤波器组成滤波器组,低频处滤波器密集,门限值大,高频处滤波器稀疏,门限值低。恰好对应了频率越高人耳越迟钝这一客观规律。上图所示的滤波器形式叫做等面积梅尔滤波器(Mel-filter bank with same bank area),在人声领域(语音识别,说话人辨认)等领域应用广泛,但是如果用到非人声领域,就会丢掉很多高频信息。这时我们更喜欢的或许是等高梅尔滤波器(Mel-filter bank with same bank height):
    这里写图片描述

    至于梅尔滤波器怎么生成的(各个三角滤波器起始频率和终止频率怎么得到,等面积梅尔滤波器最高门限值怎么得到)这个问题,我列在后面的参考文献和博客可以回答你。但如果你只是想使用梅尔滤波器组得到梅尔频率谱,并不关心它怎么得到的,那么你只需要关注下面的代码段:

    import numpy as np
    import librosa
    
    melW=librosa.filters.mel(fs=44100,n_fft=1024,n_mels=40,fmin=0.,fmax=22100)
    melW /= np.max(melW,axis=-1)[:,None]
    melX = np.dot(X,melW.T)
    
     
     

      其中,变量X是上一小节代码段得到的声谱,melX就是我们说的梅尔频谱。librosa库是python中的语音和信号处理的专业库,具体说明参见:http://librosa.github.io/librosa/generated/librosa.filters.mel.html#librosa.filters.mel

      我们知道梅尔频谱了,那么梅尔倒谱是怎么回事呢?
      这里涉及到倒谱分析的概念,在附录一(大神zouxy09的博客)介绍的很详细了。记住一句话,在梅尔频谱上做倒谱分析(取对数,做DCT变换)就得到了梅尔倒谱。这里通过一段代码展示梅尔倒谱怎么得到的:

      import librosa
      melM = librosa.feature.mfcc(wav,sr=44100,n_mfcc=20)
       
       

        而librosa.feature.mfcc这个函数内部是这样的:

        # -- Mel spectrogram and MFCCs -- #
        def mfcc(y=None, sr=22050, S=None, n_mfcc=20, **kwargs):
            if S is None:
                S = logamplitude(melspectrogram(y=y, sr=sr, **kwargs))
        
            return np.dot(filters.dct(n_mfcc, S.shape[0]), S)
         
         

          可以看出,如果只给定原始的时域信号(即S参数为None),librosa会先通过melspectrogram()函数先提取时域信号y的梅尔频谱,存放到S中,再通过filters.dct()函数做dct变换得到y的梅尔倒谱系数。

          感谢librosa可以使我们方便地提取这些有用的声音特征!!

          附录

          【1】http://blog.csdn.net/zouxy09/article/details/9156785/
          【2】http://blog.sina.com.cn/s/blog_892508d501012px5.html
          【3】https://en.wikipedia.org/wiki/Mel-frequency_cepstrum

          转载自 https://blog.csdn.net/qq_28006327/article/details/59129110
          • 5
            点赞
          • 16
            收藏
            觉得还不错? 一键收藏
          • 0
            评论
          在MATLAB中绘制梅尔频谱,可以按照以下步骤进行: 1. 首先,将音频信号加载到MATLAB中。你可以使用`audioread`函数来读取音频文件或直接使用已有的音频信号。 2. 将音频信号通过短时傅里叶变换(STFT)转换为时频表示。你可以使用`spectrogram`函数来实现这一步骤。 ```matlab [s, fs] = audioread('your_audio_file.wav'); % 读取音频文件,s为音频信号,fs为采样率 window = hamming(window_length); % 定义窗函数,例如汉明窗 noverlap = window_length - hop_size; % 计算重叠的样本数 [S, f, t] = spectrogram(s, window, noverlap, NFFT, fs); % 进行短时傅里叶变换 ``` 其中,`window_length`是窗口的长度,`hop_size`是帧移的样本数,`NFFT`是FFT的点数。 3. 计算梅尔滤波器组的中心频率。你可以使用以下代码计算梅尔滤波器组的中心频率: ```matlab num_filters = 26; % 梅尔滤波器的数量 f_min = 0; % 最低频率 f_max = fs/2; % 最高频率 mel_min = hz2mel(f_min); % 将最低频率转换为梅尔频率 mel_max = hz2mel(f_max); % 将最高频率转换为梅尔频率 mel_centers = linspace(mel_min, mel_max, num_filters+2); % 在梅尔频率上均匀分布滤波器中心 ``` 其中,`hz2mel`是将赫兹频率转换为梅尔频率的函数。 4. 将频谱转换为梅尔频谱。你可以使用以下代码将频谱转换为梅尔频谱: ```matlab mel_filters = melFilterBank(fs, NFFT, mel_centers); % 计算梅尔滤波器组 mel_spectrum = mel_filters * abs(S); % 将频谱乘以梅尔滤波器组 ``` 其中,`melFilterBank`是一个自定义函数,用于计算梅尔滤波器组。 5. 绘制梅尔频谱。你可以使用以下代码绘制梅尔频谱: ```matlab figure; imagesc(t, mel_centers, 10*log10(mel_spectrum)); % 绘制梅尔频谱 axis xy; % 设置y轴方向为正方向 xlabel('时间(秒)'); ylabel('梅尔频率(Hz)'); colorbar; % 添加颜色条 ``` 这样,你就可以在MATLAB中绘制出梅尔频谱了。注意,上述代码中的函数和变量名仅供参考,具体实现需要根据你的需求进行调整。
          评论
          添加红包

          请填写红包祝福语或标题

          红包个数最小为10个

          红包金额最低5元

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

          抵扣说明:

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

          余额充值