语谱图(一) Spectrogram 的定义与机理

在这里插入图片描述

1. 语谱图 spectrogram

在音频、语音信号处理领域,我们需要将信号转换成对应的语谱图(spectrogram),将语谱图上的数据作为信号的特征。

语谱图的横坐标是时间,纵坐标是频率,坐标点值为语音数据能量。由于是采用二维平面表达三维信息,所以能量值的大小是通过颜色来表示的,颜色深,表示该点的语音能量越强。

在这里插入图片描述

2. 语谱图形成过程

  1. 信号预加重
  2. 对信号进行分帧加窗,进行STFT, 得到每帧信号的频谱图;
  3. 对频谱图进行旋转 加映射;
  4. 将变换后的多帧频谱进行拼接, 形成语谱图;

3. 语谱图的具体实现步骤

3.1 预加重

因为语音信号的功率谱随频率的增加而减小,

导致语音的大部分能量都集中在低频部分

从而导致高频部分的信噪比很低。
因此一般使用一阶高通滤波器去提升信号在高频部分的信噪比。

对语音进行完预加重后,然后就是分帧加窗操作;

3.2 分帧与加窗

对于一段语音,以10ms~30ms 为一帧,为了保证帧与帧之间平滑过渡保持连续性,帧与帧之间会有重叠。

一段语音信号x(t) , 通过分帧之后, 数据由一维信号变为二维信号;

分帧之后,变为x(m,n)
m为帧长, 代表每一帧的长度;
n 为帧的个数, n 列代 n个帧;

下图是分帧加窗的示例 , 这段语音被分为很多帧;请添加图片描述

3.3 语谱图的形成原理

3.3.1 频谱spectrum 的产生

将每一帧的数据都进行FFT变换(严格来讲, 每帧数据加窗后做FFT , 称之为STFT),由x(m,n) 得到X(m,n)。

X(m,n) 称作频谱, 反应了频率与能量之间的关系。

频谱图:
在这里插入图片描述

在实际使用中,频谱图有三种,即

  1. 线性振幅谱、

  2. 对数振幅谱:(对数振幅谱中各谱线的振幅都作了对数计算,所以其纵坐标的单位是dB分贝)

  3. 自功率谱

这个变换的目的是使那些振幅较低的成分相对高振幅成分得以拉高,以便观察掩盖在低幅噪声中的周期信号
在这里插入图片描述
上图反应了,每帧信号对其做FFT 变换(更具体点,是通过短时FFT计算)。

每帧语音都对应于一个频谱spectrum, 如图中spectrum 所示。

注意:短时傅立叶变换(STFT),返回一个复数矩阵使得D(f,t)
复数的实部:np.abs(D(f,t))频率的振幅
复数的虚部:np.angle(D(f,t))频率的相位

3.3.2 单帧语音的频谱处理

FFT (spectrum)  ——>  rotated 90 ( spectrum )  --->  project amplitude
我们取出其中一帧语音的频谱,做如下处理:

  1. 原始一帧语音的频谱,换一种表达方式,使用坐标表示出来, 横轴代表频率, 纵轴代表幅度值;

  2. 将该坐标轴旋转 90 度,横轴代表幅度值,纵轴代表频率;

  3. 对幅度值进行映射,通过量化的方式,0表示白,255表示黑色。幅度值越大,相应的区域越黑, 从而去除了幅度值,这个维度, 多出一个维度用作表达其他信息;

至此,我们应该明白,对频谱图进行上述操作,
是为了去除了幅度值这个维度, 多出一个维度用作表达 时间这个维度信息

3.3.3 对多帧语音的频谱进行拼接

  1. 对多帧频谱, 重复上述单帧频谱的操作;

  2. 将变换后的多帧频谱, 在时间维度上,进行拼接, 从而形成了多帧信号的语谱图;
    spectrogram
    这样就可以显示一段语音而不是一帧语音的功率谱,而且可以直观的看到静态和动态的信息。

3.4 STFT的运行流程

  1. 概念——STFT短时傅里叶变换:STFT短时傅里叶变换,实际上是对一系列加窗数据做FFT。有的地方也会提到DCT(离散傅里叶变换),而DCT跟FFT的关系就是:FFT是实现DCT的一种快速算法。

  2. 概念——声谱图:对原始信号进行分帧加窗后,可以得到很多帧,对每一帧做FFT(快速傅里叶变换),傅里叶变换的作用是把时域信号转为频域信号,把每一帧FFT后的频域信号(频谱图)在时间上堆叠起来就可以得到声谱图。

  3. FFT有个参数N_fft, 简写为N,表示对一帧内多少个点做FFT,如果一帧里面的点的个数小于N就会zero-padding到N的长度。每个点对应一个频率区间, 频率区间是等间隔,即频率分辨率: 
    f r e q b i n = F s N f f t freq_{bin} = \frac{F_s}{N_{fft}} freqbin=NfftFs

已知,stft 出来的矩阵是[ 1+ N f f t 2 \frac{N_{fft}}{2} 2Nfft, n_frames],  则纵轴,频率轴的划分为这么多份,小n 属于[1, 1+ N f f t 2 \frac{N_{fft}}{2} 2Nfft ]

  • 某一点n(n从1开始)表示的频率为 F n = ( n − 1 ) ∗ F s / N F_n=(n−1)∗Fs/N Fn=(n1)Fs/N
  • 第一个点(n=1,Fn等于0)表示直流信号,
  • 纵坐标的中间点, 代表该频率bin 所对应的频率;
  • 最后一个点为 1+ N f f t 2 \frac{N_{fft}}{2} 2Nfft, 代表的是采样频率的一半,即Fs/2。
  1. FFT后我们可以得到N个频点,比如,采样频率为16000,N为1600,那么FFT后就会得到1600个点,FFT得到的1600个值的模可以表示1600个频点对应的振幅。因为FFT具有对称性,当N为偶数时取N/2+1个点,当N为奇数时,取(N+1)/2个点,比如N为512时最后会得到257个值。

4. 为什么需要语谱图?

因为声谱图中有很多重要的特征, 比如音素特征;
共振峰特征(formants 即频谱图中的峰值)
以及观察他们的转变趋势, 可以更好的识别音频;

  • 语音信号的时间-频率表示方法:

  • 语谱图是研究语音(音素Phone)的工具

  • 语音学家对音素Phone及其特性进行直观研究

  • 隐马尔科夫模型隐含了语音到文本系统的语谱图模型
    有助于评估文本到语音系统——一个高质量的文本到语音系统应该产生合成语音,其频谱图应该与自然句子几乎一致

1
在这里插入图片描述

5. 频谱与语谱图之间的关系

从上述分析, 单帧的信号的频谱可以看出,

语谱图这个概念的出现, 是为了弥补频谱图,丢失了时间这个维度的信息, 故而增加了时间这个维度。

具体的方式, 就是将频谱中的幅度值 这个维度替换掉(使用颜色的深度来表示),从多出了一个维度;

而这个多出的维度, 便是留作扩展出,时间这个维度的信息;

所以, 语谱图使用二维的表现形式, 涵盖了三个维度的信息
(纵轴:频率, 横轴: 时间; 颜色深度: 幅度值大小)

6. 语谱图的coding:

代码实现:

import matplotlib.pyplot as plt
import librosa
import numpy as np
import soundfile as sf
import python_speech_features as psf
import librosa
import librosa.display
# Spectrogram步骤,
# Step 1: 预加重
# Step 2: 分帧
# Step 3: 加窗
# Step 4: FFT
# Step 5: 幅值平方
# Step 6: 对数功率
def preemphasis(signal, coeff=0.95):return np.append(signal[1], signal[1:] - coeff * signal[:-1])def pow_spec(frames, NFFT):complex_spec = np.fft.rfft(frames, NFFT)return 1 / NFFT * np.square(np.abs(complex_spec))
def frame_sig(sig, frame_len, frame_step, win_func):''':param sig: 输入的语音信号:param frame_len: 帧长:param frame_step: 帧移:param win_func: 窗函数:return: array of frames, num_frame * frame_len'''slen = len(sig)if slen <= frame_len:num_frames = 1else:# np.ceil(), 向上取整num_frames = 1 + int(np.ceil((slen - frame_len) / frame_step))padlen = int( (num_frames - 1) * frame_step + frame_len)# 将信号补长,使得(slen - frame_len) /frame_step整除zeros = np.zeros((padlen - slen,))padSig = np.concatenate((sig, zeros))indices = np.tile(np.arange(0, frame_len), (num_frames, 1)) + np.tile(np.arange(0, num_frames*frame_step, frame_step), (frame_len, 1)).Tindices = np.array(indices, dtype=np.int32)frames = padSig[indices]win = np.tile(win_func(frame_len), (num_frames, 1))return frames * winy, sr = sf.read('q1.wav')
# 预加重
y = preemphasis(y, coeff=0.98)
# 分帧加窗
frames = frame_sig(y, frame_len=2048, frame_step=512, win_func=np.hanning)
# FFT及幅值平方
feature = pow_spec(frames, NFFT=2048)
# 对数功率及绘图.
librosa.display.specshow(librosa.power_to_db(feature.T),sr=sr, x_axis='time', y_axis='linear')
plt.title('Spectrogram')
plt.colorbar(format='%+2.0f dB')
plt.tight_layout()
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/69543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简易实现QT中的virtualkeyboard及问题总结

文章目录 前言&#xff1a;一、虚拟键盘的实现综合代码 二、为什么选用QWidget而不适用QDialog实现键盘三、从窗体a拉起窗体b后&#xff0c;窗体b闪退问题的探讨四、关闭主窗口时子窗口未关闭的问题 前言&#xff1a; 本文章主要包含四部分&#xff1a; 虚拟键盘的实现&#…

嵌入式基础-电路

目录 1、电流 1.1电流方向 1.2交流电和直流电 2、电压 3、电阻 4、欧姆定律 1、电流 电流是指单位时间内通过导体的电荷量&#xff0c;用符号I表示&#xff0c;单位是安培&#xff08;A&#xff09;。电流是电磁学中的基本量纲之一&#xff0c;是七个基本量纲之一。电流的…

《Effective C++中文版,第三版》读书笔记7

条款41&#xff1a; 了解隐式接口和编译期多态 隐式接口&#xff1a; ​ 仅仅由一组有效表达式构成&#xff0c;表达式自身可能看起来很复杂&#xff0c;但它们要求的约束条件一般而言相当直接而明确。 显式接口&#xff1a; ​ 通常由函数的签名式&#xff08;也就是函数名…

【模方ModelFun】实景三维建模和修模4.0.7最新版安装包以及图文安装教程

模方ModelFun 具有多种功能&#xff0c;旨在帮助用户进行实景三维建模和修模。以下是一些主要功能的简要介绍&#xff1a; 实景三维建模&#xff1a;【模方ModelFun】提供了自动化的实景三维重建功能&#xff0c;可以从实景图像中提取几何形状和纹理信息&#xff0c;生成高质量…

golang 多个struct 转换融合为一个json,平级融合或者多级融合

1. 平级融合&#xff0c;就是下面例子&#xff0c;虽然A在B里面&#xff0c;但是A在struct B里面没有名字&#xff0c;输出结果就是A 和B在同一级的json下面。 package mainimport ("encoding/json""fmt" )type A struct {Name string json:"…

【Vue-Element-Admin】导出el-table全部数据

背景 因为el-table实现了分页查询&#xff0c;所以想要实现el-table需要重新编写一个查询全部数据的方法 查询全部数据 listQuery: export default{return{listQuery:{//page:1,//limit:20,//如果想兼容按条件导出&#xff0c;可以定义查询条件age:undefined,sex:undefined…

Java 加了@PreAuthorize注解的接口在Postman中访问

1. 首先&#xff0c;你需要获取一个有效的用户token&#xff0c;该token应包含了相应的接口权限。你可以通过登录或其他身份验证方式来获取token。2. 打开Postman&#xff0c;并确保已选择正确的HTTP方法&#xff08;GET、POST等&#xff09;。3. 在请求的Headers部分&#xff…

【python爬虫】12.建立你的爬虫大军

文章目录 前言协程是什么多协程的用法gevent库queue模块 拓展复习复习 前言 照旧来回顾上一关的知识点&#xff01;上一关我们学习如何将爬虫的结果发送邮件&#xff0c;和定时执行爬虫。 关于邮件&#xff0c;它是这样一种流程&#xff1a; 我们要用到的模块是smtplib和emai…

解决npm run build 打包出现XXXX.js as it exceeds the max of 500KB.

问题描述&#xff1a; npm run build 时出现下面的问题&#xff1a; Note: The code generator has deoptimised the styling of D:\base\node_modules\_element-ui2.15.12element-ui\lib\element-ui.common.js as it exceeds the max of 500KB.在项目的根目录加粗样式下找到 …

论文笔记: 深度学习速度模型构建的层次迁移学习方法 (未完)

摘要: 分享对论文的理解, 原文见 Jrome Simon, Gabriel Fabien-Ouellet, Erwan Gloaguen, and Ishan Khurjekar, Hierarchical transfer learning for deep learning velocity model building, Geophysics, 2003, R79–R93. 这次的层次迁移应该指从 1D 到 2D 再到 3D. 摘要 深…

程序产生自我意识,创造人工生命

偶然发现一个大佬研究了一个很有意思的项目&#xff0c;研究了好几年&#xff0c;让程序产生自我意识诞生人工生命&#xff0c;感觉10年后肯定是继Chart GPT之后的又一个风口&#xff0c;在这里记录一下分享给大家&#xff0c;这个项目在git上有开源&#xff0c;开源地址&#…

@Controller和@RestController注解区别

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;SpringBoot、Spring、注解、Controller、RestController☀️每日 一言&#xff1a;弗雷尔卓德是个好地方&#xff0c;可以造东西、打架、大吃一顿&#xff0c;啊~~ 甜蜜的家园呐 ——《英雄联盟》…

Linux 权限

什么是权限 在Linux下有两种用户&#xff0c;分别是超级用户&#xff08;root&#xff09;和普通用户。超级用户可以在Linux下做任何事情&#xff0c;几乎不受限制&#xff0c;而普通用户一般只能在自己的工作目录下&#xff08;/home/xxx&#xff09;工作&#xff0c;以及在系…

HTML5-3-表格

文章目录 属性边框属性标题跨行和跨列单元格边距 HTML 表格由 <table> 标签来定义。 tr&#xff1a;tr 是 table row 的缩写&#xff0c;表示表格的一行。td&#xff1a;td 是 table data 的缩写&#xff0c;表示表格的数据单元格。th&#xff1a;th 是 table header的缩…

flask使用Flask-Mail实现邮件发送

Flask-Mail可以实现邮件的发送&#xff0c;并且可以和 Flask 集成&#xff0c;让我们更方便地实现此功能。 1、安装 使用pip安装&#xff1a; $ pip install Flask-Mail或下载源码安装&#xff1a; $ git clone https://github.com/mattupstate/flask-mail.git $ cd flask-…

Java到底是值传递还是引用传递【通俗易懂】

我相信很多刚学Java的小伙伴都很难理解Java到底是值传递还是引用传递的问题&#xff0c;但肯定背过这道面试题。确实&#xff0c;Java就是值传递&#xff0c;那什么原理呢&#xff1f;请往下看。 我们先看一段代码&#xff1a;分析一下这两句打印的结果分别是什么。 public c…

R3LIVE源码解析(9) — R3LIVE中r3live_lio.cpp文件

目录 1 r3live_lio.cpp文件简介 2 r3live_lio.cpp源码解析 1 r3live_lio.cpp文件简介 在r3live.cpp文件中创建LIO线程后&#xff0c;R3LIVE中的LIO线程本质上整体流程和FAST-LIO2基本一致。 2 r3live_lio.cpp源码解析 函数最开始会进行一系列的声明和定义&#xff0c;发布的…

前端面试基础面试题——5

1.react 和 vue 的区别是什么&#xff1f; 2.虚拟DOM的原理&#xff1f;优点与缺点&#xff1f; 3.类组件和函数组件之间的区别是&#xff1f; 4.state 和 props 区别是什么&#xff1f; 5.React 中 refs 是做什么的&#xff1f; 6.什么是高阶组件&#xff1f; 7.讲讲什么…

重装系统后,MySQL install错误,找不到dll文件,或者应用程序错误

文章目录 1.找不到某某dll文件2.mysqld.exe - 应用程序错误使用DX工具直接修复 1.找不到某某dll文件 由于找不到VCRUNTIME140_1.dll或者MSVCP120.dll&#xff0c;无法继续执行代码&#xff0c;重新安装程序可能会解决此问题。 在使用一台重装系统过的电脑&#xff0c;再次重新…

ModStartCMS v7.2.0 匿名点赞功能,注册站内信

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…