librosa 语音库(二)STFT 的实现

article/2025/10/7 7:17:02

librosa是一个应用广泛的音频处理python库。

librosa中有一个方法叫做stft,功能是求音频的短时傅里叶变换, librosa.stft 返回是一个矩阵

短时傅立叶变换(STFT),返回一个复数矩阵使得D(f,t)

  1. 当调用的形式是 np.abs( stft() ), 代表的是取, 取出复数矩阵的实部,即频率的振幅。

  2. 当调用的形式是 np.angle( stft() ), 代表的是取, 取出复数矩阵的虚部,即频率的相位。

This function returns a complex-valued matrix D such that
- np.abs(D[f, t]) is the magnitude of frequency bin f
at frame t, and
- np.angle(D[f, t]) is the phase of frequency bin f
at frame t.

The integers t and f can be converted to physical units by means
of the utility functions frames_to_sample and fft_frequencies.

1. librosa.stft函数

librosa.stft(y, n_fft=2048, hop_length=None, win_length=None, window='hann', center=True, pad_mode='reflect')

参数:

  • y:音频时间序列

  • n_fft:FFT窗口大小,n_fft=hop_length+overlapping

  • hop_length:帧移,如果未指定,则默认win_length / 4。

  • win_length:每一帧音频都由window()加窗。窗长win_length,然后用零填充以匹配N_FFT。默认win_length=n_fft。

  • window:字符串,元组,数字,函数 shape =(n_fft, )
    窗口(字符串,元组或数字);
    窗函数,例如scipy.signal.hanning
    长度为n_fft的向量或数组

  • center:bool
    如果为True,则填充信号y,以使帧 D [:, t]以y [t * hop_length]为中心。
    如果为False,则D [:, t]从y [t * hop_length]开始

  • dtype:D的复数值类型。默认值为64-bit complex复数

  • pad_mode:如果center = True,则在信号的边缘使用填充模式。默认情况下,STFT使用reflection padding。

返回:
STFT矩阵,shape = (1+ n f f t 2 \frac{n_{fft}}{2} 2nfft, n f r a m e s n_{frames} nframes )

2. stft的输出帧数

音频短时傅里叶变换后,在对音频取幅值,可以得到音频的线性谱。

对线性谱进行mel刻度的加权求和,可以得到语音识别和语音合成中常用的mel谱。

短时傅里叶变换的过程是先对音频分帧,再分别对每一帧傅里叶变换。

在应用stft方法求解短时傅里叶变换时,发现求出的特征帧的数目有点反常。

比如我有一个长度是400个点的音频,如果帧长是100,那么我自然而然的想到,最后应当得到4帧。

但实际不是这个样子的,实际的帧数为5帧。这就有点神奇了。

分析了一下,原因如下。

在这里插入图片描述
为了方便讨论,假设帧长为200,帧移为100,fft size是200。

上图中是一条长度为430的音频,在经过stft后,输出5帧。

过程是这样的。

  1. 在音频的左右两侧padding,padding size是fft size的一半

  2. 现在音频长度变成了430 + 200 = 630

  3. 总帧数为(630 - 100) // 100

  4. 如上图示意,最后得到5帧

所以,librosa求stft的输出帧数,当音频长度在400 <= x < 500之间时,输出帧数为5。

推广开来,音频求stft的输出帧数都是 audio_length // hop_length + 1。

这个东西有什么用呢?在用到帧和原始采样点相对应的场景下,千万别忘了padding 0 到帧数那么多,再去进行其他操作。

如果有兴趣可以写代码自己验证一下。

3.  各个参数的分析

n_fftFFT点数,也是补零后每一帧信号的长度。输出的行数与n_fft有关,为n_fft/2+1

hop_length帧移。可以理解为下一帧相对上一帧移动了多少个采样点。使用更小的值可以在不减少频率分辨率的情况下增加输出的列数。默认是win_length/4

win_length窗长。使用该长度的窗函数截取语音后得到每一帧信号。更小的值会在牺牲STFT频率分辨率的同时增加其时间分辨率

center默认为Ture,即在原信号r的左右两边分别补上n_fft//2个点,使得第t帧的信号以r[thop_length]为中心点。当为False时,第t帧的信号以r[thop_length]为起点

pad_mode默认为”reflect”,即在center=True时,采用镜像模式对r进行填补,比如[1, 2, 3, 4]会被补为[3, 2, 1, 2, 3, 4, 3 ,2]

3.1 时频分辨率

时间分辨率:

liborsa中,时间分辨率(Temporal Resolution)的解释为:在时域中分辨出紧邻的冲击的能力。

频率分辨率:

频率分辨率(Frequency Resolution)的解释为:在频域中分辨出紧邻的单频率音的能力。

与二者相关的参数分别是win_length和n_fft,表现为win_length越小,时间分辨率越精准;n_fft越大,频率分辨率越精准。

但是,在实际中,不能只按照win_length <= n_fft来选取它们。

在实际操作中,当每帧长度不等于FFT点数时,要将窗函数的两边同时补零到n_fft长度且对每帧数据加窗(参考librosa和torch.stft()的)后,才能进行FFT

但这不并不是说因为会自动补零,就可以随便选取win_length。

3.2 如何提升分辨率

(T)为原始数据的时长, N f f t \N_{fft} Nfft为FFT点数。当(T)不变时,不论如何提升 N f f t \N_{fft} Nfft,都不能提高波形频率分辨率(\Delta R_w)。

对此的解释是:“在时域或频域内补零,只能提升另一个域内的插值密度(Interpolation-density),而非提升分辨率。”

为了提升FFT分辨率,我们要收集更多的原始数据,做点数更大的FFT.

要提升频率分辨率,必须同时增大每帧数据的长度win_length和FFT点数n_fft.

注意, 这里的每帧的数据长度 win_length, 指的是没有通过补零得到的原始数据。

3.3 帧移长度的选取

既然win_length和n_fft的值都不能随便选,那么hop_length…

没错,在选择窗函数和帧移时,必须要满足Constant Overlap-Add(COLA):

∑ m = − ∞ ∞ w ( n − m R ) = 1 , ∀ n ∈ Z (3) \begin{equation} \sum\limits_{m=-\infty}^{\infty}w(n-mR)=1,\forall n\in\mathbb{Z} \end{equation} \tag{3} m=w(nmR)=1,nZ(3)

COLA确保了输入中的每个点都有同样的权值,从而避免出现时域混叠(aliasing),以及确保ISTFT能够完美地重构原信号。这是因为,在对语音进行分帧加窗时,每帧之间存在重叠的部分,且该部分在ISTFT后也会存在。

比如使用矩形窗就不能完美地重构原信号。

在STFT中常用的 1 2 \frac{1}{2} 21 2 3 \frac{2}{3} 32 1 4 \frac{1}{4} 41重叠率的汉宁窗符合COLA。

窗函数和帧移的选取并不是随意的。

默认center=Ture,要在原数据左右两端补上 N f f t 2 \frac{N_{fft}}{2} 2Nfft个点,人为地让原始语音在能够完美重构信号的范围内。

4. code

@cache(level=20)
def stft(y,n_fft=2048,hop_length=None,win_length=None,window="hann",center=True,dtype=None,pad_mode="reflect",
):"""Short-time Fourier transform (STFT).The STFT represents a signal in the time-frequency domain bycomputing discrete Fourier transforms (DFT) over short overlappingwindows.This function returns a complex-valued matrix D such that- ``np.abs(D[f, t])`` is the magnitude of frequency bin ``f``at frame ``t``, and- ``np.angle(D[f, t])`` is the phase of frequency bin ``f``at frame ``t``.The integers ``t`` and ``f`` can be converted to physical units by meansof the utility functions `frames_to_sample` and `fft_frequencies`.Parameters----------y : np.ndarray [shape=(n,)], real-valuedinput signaln_fft : int > 0 [scalar]length of the windowed signal after padding with zeros.The number of rows in the STFT matrix ``D`` is ``(1 + n_fft/2)``.The default value, ``n_fft=2048`` samples, corresponds to a physicalduration of 93 milliseconds at a sample rate of 22050 Hz, i.e. thedefault sample rate in librosa. This value is well adapted for musicsignals. However, in speech processing, the recommended value is 512,corresponding to 23 milliseconds at a sample rate of 22050 Hz.In any case, we recommend setting ``n_fft`` to a power of two foroptimizing the speed of the fast Fourier transform (FFT) algorithm.hop_length : int > 0 [scalar]number of audio samples between adjacent STFT columns.Smaller values increase the number of columns in ``D`` withoutaffecting the frequency resolution of the STFT.If unspecified, defaults to ``win_length // 4`` (see below).win_length : int <= n_fft [scalar]Each frame of audio is windowed by ``window`` of length ``win_length``and then padded with zeros to match ``n_fft``.Smaller values improve the temporal resolution of the STFT (i.e. theability to discriminate impulses that are closely spaced in time)at the expense of frequency resolution (i.e. the ability to discriminatepure tones that are closely spaced in frequency). This effect is knownas the time-frequency localization trade-off and needs to be adjustedaccording to the properties of the input signal ``y``.If unspecified, defaults to ``win_length = n_fft``.window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]Either:- a window specification (string, tuple, or number);see `scipy.signal.get_window`- a window function, such as `scipy.signal.windows.hann`- a vector or array of length ``n_fft``Defaults to a raised cosine window (`'hann'`), which is adequate formost applications in audio signal processing... see also:: `filters.get_window`center : booleanIf ``True``, the signal ``y`` is padded so that frame``D[:, t]`` is centered at ``y[t * hop_length]``.If ``False``, then ``D[:, t]`` begins at ``y[t * hop_length]``.Defaults to ``True``,  which simplifies the alignment of ``D`` onto atime grid by means of `librosa.frames_to_samples`.Note, however, that ``center`` must be set to `False` when analyzingsignals with `librosa.stream`... see also:: `librosa.stream`dtype : np.dtype, optionalComplex numeric type for ``D``.  Default is inferred to match theprecision of the input signal.pad_mode : string or functionIf ``center=True``, this argument is passed to `np.pad` for paddingthe edges of the signal ``y``. By default (``pad_mode="reflect"``),``y`` is padded on both sides with its own reflection, mirrored aroundits first and last sample respectively.If ``center=False``,  this argument is ignored... see also:: `numpy.pad`Returns-------D : np.ndarray [shape=(1 + n_fft/2, n_frames), dtype=dtype]Complex-valued matrix of short-term Fourier transformcoefficients.See Also--------istft : Inverse STFTreassigned_spectrogram : Time-frequency reassigned spectrogramNotes-----This function caches at level 20.Examples-------->>> y, sr = librosa.load(librosa.ex('trumpet'))>>> S = np.abs(librosa.stft(y))>>> Sarray([[5.395e-03, 3.332e-03, ..., 9.862e-07, 1.201e-05],[3.244e-03, 2.690e-03, ..., 9.536e-07, 1.201e-05],...,[7.523e-05, 3.722e-05, ..., 1.188e-04, 1.031e-03],[7.640e-05, 3.944e-05, ..., 5.180e-04, 1.346e-03]],dtype=float32)Use left-aligned frames, instead of centered frames>>> S_left = librosa.stft(y, center=False)Use a shorter hop length>>> D_short = librosa.stft(y, hop_length=64)Display a spectrogram>>> import matplotlib.pyplot as plt>>> fig, ax = plt.subplots()>>> img = librosa.display.specshow(librosa.amplitude_to_db(S,...                                                        ref=np.max),...                                y_axis='log', x_axis='time', ax=ax)>>> ax.set_title('Power spectrogram')>>> fig.colorbar(img, ax=ax, format="%+2.0f dB")"""# By default, use the entire frameif win_length is None:win_length = n_fft# Set the default hop, if it's not already specifiedif hop_length is None:hop_length = int(win_length // 4)fft_window = get_window(window, win_length, fftbins=True)# Pad the window out to n_fft sizefft_window = util.pad_center(fft_window, n_fft)# Reshape so that the window can be broadcastfft_window = fft_window.reshape((-1, 1))# Check audio is validutil.valid_audio(y)# Pad the time series so that frames are centeredif center:if n_fft > y.shape[-1]:warnings.warn("n_fft={} is too small for input signal of length={}".format(n_fft, y.shape[-1]))y = np.pad(y, int(n_fft // 2), mode=pad_mode)elif n_fft > y.shape[-1]:raise ParameterError("n_fft={} is too large for input signal of length={}".format(n_fft, y.shape[-1]))# Window the time series.y_frames = util.frame(y, frame_length=n_fft, hop_length=hop_length)if dtype is None:dtype = util.dtype_r2c(y.dtype)# Pre-allocate the STFT matrixstft_matrix = np.empty((int(1 + n_fft // 2), y_frames.shape[1]), dtype=dtype, order="F")fft = get_fftlib()# how many columns can we fit within MAX_MEM_BLOCK?n_columns = util.MAX_MEM_BLOCK // (stft_matrix.shape[0] * stft_matrix.itemsize)n_columns = max(n_columns, 1)for bl_s in range(0, stft_matrix.shape[1], n_columns):bl_t = min(bl_s + n_columns, stft_matrix.shape[1])stft_matrix[:, bl_s:bl_t] = fft.rfft(fft_window * y_frames[:, bl_s:bl_t], axis=0)return stft_matrix

参考:
参考文章


http://chatgpt.dhexx.cn/article/nTDgqjeD.shtml

相关文章

python的opencv操作记录(七)——短时傅里叶变换(stft)

文章目录 DCT-傅立叶变换的局限性STFT 短时傅里叶变换从另一个角度来理解图像的“时域”数据看看fs和t这两个参数再看看怎么划分窗口最后看另外两个出参Zxx返回结构 图像的stft DCT-傅立叶变换的局限性 接上一篇DCT的文章&#xff0c;DCT只提取了整个信号域的频率信息&#xf…

傅里叶变换@(stft和istft)

一、窗函数之短时傅里叶变换stft 前提&#xff1a; 傅里叶变换是针对平稳信号的&#xff0c;但是很多实际应用中的信号都是非平稳的&#xff0c;如果要计算其傅里叶变换&#xff0c;需要假设其周期无限长&#xff0c;然后对这个无限长的信号做变换分析。但是这种无限长信号分…

scipy短时傅里叶分析STFT

scipy短时傅里叶分析 基本原理&#xff1a; 为了使STFT能够通过STFT逆变换反变换&#xff0c;信号加窗必须服从“非零重叠加”(NOLA)的约束&#xff0c;输入信号必须具有完整的加窗覆盖即 ( x . s h a p e [ a x i s ] − n p e r s e g ) (x.shape[axis] - nperseg) % (nper…

STFT笔记

因为不懂这个被鄙视了&#xff0c;调包侠来补作业。 基础知识 FFT(fast fourier transfrom)快速傅里叶变换。 推荐阅读《深入浅出的讲解傅里叶变换&#xff08;真正的通俗易懂&#xff09;》&#xff0c; 《梅尔频率倒谱系数&#xff08;MFCC&#xff09;》。 频谱只获得了频…

利用短时傅里叶变换(STFT)对信号进行时频谱分析和去噪声

利用短时傅里叶变换&#xff08;STFT&#xff09;对信号进行时频谱分析和去噪声 1、背景 傅里叶变换&#xff08;TF&#xff09;对频谱的描绘是“全局性”的&#xff0c;不能反映时间维度局部区域上的特征,人们虽然从傅立叶变换能清楚地看到一整段信号包含的每一个频率的分量值…

STFT(短时傅里叶变换)音频特征提取,用于语音识别 python

在各种音频相关的任务中&#xff0c;不管用什么模型或网络&#xff0c;得到所需的音频特征肯定是必要的一步。下面简单说一下STFT特征 一、原始信号 在说STFT之前&#xff0c;先说一下读入的原始信号&#xff0c;图像是在XY二维上描述的像素点的集合&#xff0c;相应的&#x…

STFT原理及MATLAB代码

原文地址&#xff1a;http://blog.csdn.net/shengzhadon/article/details/46811923 一、先说说STFT的理论 1.概念和特点 STFT&#xff08;short-time Fourier transform&#xff0c;短时傅里叶变换&#xff09;是和傅里叶变换相关的一种数学变换&#xff0c;用以确定时变信号其…

nvme分区选mbr还是guid_win7安装系统硬盘模式mbr和guid选哪个?

有很多系统之家的用户&#xff0c;还是喜欢安装win7系统的。但是在新的硬盘里面我们要分区的话&#xff0c;会出现mbr和guid是硬盘分区的两个格式&#xff0c;很多用户在做系统的时候不知道选哪个好&#xff0c;其实最好根据自己的电脑的配置&#xff0c;下面来看看详细的介绍吧…

uefi+guid分区与legacy+mbr分区_硬盘分区表格式GUID和MBR知识普及

我们的电脑硬盘分区格式一共有两种,一种是GUID(GPT),一种是MBR。 啥是硬盘分区呢?举个例子你就明白了,很多人去买电脑的时候,比如你买的电脑只有一块硬盘,店家就会给你分区,把这一块硬盘分成好几个区,比如分成了系统,软件,文档这样三个,那么你打开【我的电脑】后就会…

nvme分区选mbr还是guid_SSD里的特例:NVME固态改MBR格式、装Win7

问题一:NVME固态是否支持MBR文件格式: 场景:前几天朋友兴致冲冲的买了个建兴T10,准备好好体验一下。但是正当他吃着火锅,唱着歌,突然就给麻匪劫了——电脑系统竟然接二连三莫名奇妙的崩溃。 于是朋友就向我求助。由于他的电脑最近除了换了硬盘,并没有添加任何其他的硬设…

guid备份分区表crc错误_硬盘GPT和MBR分区表转换方法

随着硬盘容量越来越大,传统的MBR硬盘分区模式已经不能满足发展需要,预装win8或win10系统的硬盘默认都是GPT分区表(GUID格式),GPT识别2T以上的硬盘以及UEFI启动模式。不过在对系统进行重装时,经常会遇到无法安装在GPT或MBR硬盘中的问题,那么这个时候就需要对硬盘的分区表进…

GUID与MBR

磁盘分区表方案 全局唯一标识分区表是一个实体硬盘的分区表的结构布局的标准。 先说说目前广泛使用的磁盘分区表方案。传统的分区方案(称为MBR分区方案)是将分区信息保存到磁盘的第一个扇区(MBR扇区)中的64个字节中&#xff0c;每个分区项占用16个字节&#xff0c;这16个字节中…

如何将MBR转为GUID?这方法易于使用且安全!

为什么要将MBR转为GUID(GPT)&#xff1f; MBR代表主引导记录&#xff0c;它使用Legacy BIOS分区表。而GPT磁盘&#xff0c;也就是GUID分区表的缩写&#xff0c;是一种引入了统一可扩展固件接口 (UEFI) 的新布局。GPT磁盘有2个主要优势&#xff1a; GPT磁盘每个分区…

计算机硬盘分区信息,你知道电脑硬盘分区Guid格式和MBR格式有什么区别吗?来看看!...

现在的电脑随着技术的更新&#xff0c;传统的MBR格式虽然支持兼容&#xff0c;但是win10系统基本都使用了GUID分区格式&#xff0c;这样会让整体的系统运作得更有效率。如果还在使用MBR格式的用户想安装系统&#xff0c;没有设置好分区格式&#xff0c;容易导致安装出错&#x…

nvme分区选mbr还是guid_UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别

UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别?很多电脑小白都搞不懂UEFI、GPT、BIOS、MBR到底是什么意思,下面跟随小白系统一起深入了解下UEFI+GPT和Legacy+MBR两种模式安装的系统有什么区别吧。 一、了解专业名词 BIOS,全称"Basic Input Output System",中…

nvme分区选mbr还是guid_怎么分辨硬盘是GUID格式还是MBR格式以及怎样更改

首先我们要大概了解一下MBR和GUID是什么 mbr是指主引导记录,guid是指全局唯一标识符(其实我也不太懂这是啥),两者都是硬盘的一种启动模式(大概是这个意思,欢迎指教) 但是mbr只支持2x1024mb,也就是传统意义上的2tb的储存,并且只能分最多4个区,而guid理论上来讲可以有无…

nvme分区选mbr还是guid_系统重装,硬盘分区MBR和GPT选哪个好?看完才知原来有这讲究!...

在重装系统时,不少用户会问老毛桃电脑的硬盘选择MBR格式还是GPT格式好呢?其实,如何选择格式和你用的电脑是BIOS启动或是UEFI启动有很大的联系。我们都知道现在大家较为常用的要么是BIOS+MBR模式,要么是UEFI+GPT模式,选择任意一种模式的分区对系统运行不会造成太大的影响。…

nvme分区选mbr还是guid_重装系统时,磁盘分区MBR和GPT模式哪个好?原来还有这两种区别!...

相信大家在重装系统之前就会将电脑磁盘进行分区,毕竟只有一个分区是不可以进行重装系统的。而且磁盘分区方便管理磁盘,每个分区之间相互独立,数据不容易产生混淆。那么大家在创建磁盘分区的时候,肯定都会遇到MBR和GPT两种引导模式,这时候就会产生人生的思考:究竟应该怎么…

nvme分区选mbr还是guid_老毛桃winpe的DiskGenius分区工具使用说明

在对磁盘进行分区时,存在着一大堆的设置,到底需要如何设置?分区表是什么?如何进行4K对齐?以下操作建议PE下使用,前期需要准备:制作老毛桃U盘启动盘(U盘大小需要8G以上)。 操作指引: 起始分区操作请看:第1步 GUID分区表(GPT硬盘)操作请看:第2~7步; MBR分区表操作请看:…

服务器系统要用GUID还是MBR,win7mbr和guid应该选哪一个

win7mbr和guid是硬盘分区的两个格式&#xff0c;很多用户在做系统的时候不知道选哪个好&#xff0c;其实最好根据自己的电脑的配置&#xff0c;下面来看看详细的介绍吧。 win7mbr和guid选哪个 WIN7&#xff1a;建议MBR分区。因为Windows 7默认不支持UEFI系统安装&#xff0c;无…