Python对音频进行频谱分析

news/2024/9/19 0:48:17/ 标签: python, 开发语言

文章目录

  • 一、储备函数
    • 1.1 计时装饰器、查找最接近的值、音高频率创建与读取
    • 1.2 440音高频率表
  • 二、Pyaudio

一、储备函数

1.1 计时装饰器、查找最接近的值、音高频率创建与读取

python">import time
import math
import numpy as np
import pandas as pd# 定义时间装饰器
def timeit(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)using = (time.time() - start_time) * 1000print(f'运行时间:{using} 毫秒')return resultreturn wrapper# 普通未排序数组查找最接近的值
@timeit
def find_nearest(array, value):array = np.array(array)idx = (np.abs(array-value)).argmin()return array[idx]# 已排序数组查找最接近的值
@timeit
def find_nearest_sorted(array, value):idx = np.searchsorted(array, value, side="left")if idx > 0 and (idx == len(array) or math.fabs(value - array[idx-1]) < math.fabs(value - array[idx])):return array[idx-1]else:return array[idx]# 计算音高频率,参数一般为440、442或432
def calculate_frequency(standard_frequency):list_frequency = []for i in range(132):fre = round(standard_frequency / 32 * math.pow(2, (i-9.0) / 12),3)list_frequency.append(fre)return list_frequency[12:]# 利用计算音高创建音高频率df
@timeit
def create_frequency():df_frequency = pd.DataFrame()df_frequency['letter_name'] = ['C0', 'C♯/D♭0', 'D0', 'D♯/E♭0', 'E0', 'F0', 'F♯/G♭0', 'G0', 'G♯/A♭0', 'A0', 'A♯/B♭0', 'B0', 'C1', 'C♯/D♭1', 'D1', 'D♯/E♭1', 'E1', 'F1', 'F♯/G♭1', 'G1', 'G♯/A♭1', 'A1', 'A♯/B♭1', 'B1', 'C2', 'C♯/D♭2', 'D2', 'D♯/E♭2', 'E2', 'F2', 'F♯/G♭2', 'G2', 'G♯/A♭2', 'A2', 'A♯/B♭2', 'B2', 'C3', 'C♯/D♭3', 'D3', 'D♯/E♭3', 'E3', 'F3', 'F♯/G♭3', 'G3', 'G♯/A♭3', 'A3', 'A♯/B♭3', 'B3', 'C4', 'C♯/D♭4', 'D4', 'D♯/E♭4', 'E4', 'F4', 'F♯/G♭4', 'G4', 'G♯/A♭4', 'A4', 'A♯/B♭4', 'B4', 'C5', 'C♯/D♭5', 'D5', 'D♯/E♭5', 'E5', 'F5', 'F♯/G♭5', 'G5', 'G♯/A♭5', 'A5', 'A♯/B♭5', 'B5', 'C6', 'C♯/D♭6', 'D6', 'D♯/E♭6', 'E6', 'F6', 'F♯/G♭6', 'G6', 'G♯/A♭6', 'A6', 'A♯/B♭6', 'B6', 'C7', 'C♯/D♭7', 'D7', 'D♯/E♭7', 'E7', 'F7', 'F♯/G♭7', 'G7', 'G♯/A♭7', 'A7', 'A♯/B♭7', 'B7', 'C8', 'C♯/D♭8', 'D8', 'D♯/E♭8', 'E8', 'F8', 'F♯/G♭8', 'G8', 'G♯/A♭8', 'A8', 'A♯/B♭8', 'B8', 'C9', 'C♯/D♭9', 'D9', 'D♯/E♭9', 'E9', 'F9', 'F♯/G♭9', 'G9', 'G♯/A♭9', 'A9', 'A♯/B♭9', 'B9']df_frequency['frequency_440'] = calculate_frequency(440)df_frequency['frequency_442'] = calculate_frequency(442)return df_frequency# 利用读取音高创建音高频率df
@timeit
def read_frequency():df = pd.read_excel('f:/音高频率.xlsx', index_col='音名')letter_name = []for i in range(10):for j in df.index.to_list():letter_name.append(j.strip() + str(i))df_frequency = pd.DataFrame()df_frequency['frequency_440'] = df.stack().sort_values()df_frequency['letter_name'] = letter_namedf_frequency.reset_index(inplace=True)df_frequency = df_frequency[['letter_name', 'frequency_440']]return df_frequencydf_frequency = create_frequency()   # 2.986431121826172 毫秒
# df_frequency = read_frequency()     # 378.781795501709 毫秒df_frequency.to_excel('f:/frequency.xlsx')
print(df_frequency.loc[df_frequency['letter_name']=='A4'])

1.2 440音高频率表

在这里插入图片描述

音名0123456789
C16.35232.70365.406130.81261.63523.251046.5209341868372
C♯/D♭17.32434.64869.296138.59277.18554.371108.72217.54434.98869.8
D18.35436.70873.416146.83293.66587.331174.72349.34698.69397.3
D♯/E♭19.44538.89177.782155.56311.13622.251244.5248949789956.1
E20.60241.20382.407164.81329.63659.261318.52637527410548
F21.82743.65487.307174.61349.23698.461396.92793.85587.711175
F♯/G♭23.12546.24992.499185369.99739.99148029605919.911840
G24.548.99997.999196392783.99156831366271.912544
G♯/A♭25.95751.913103.83207.65415.3830.611661.23322.46644.913290
A27.55511022044088017603520704014080
A♯/B♭29.13558.27116.54233.08466.16932.331864.73729.37458.614917
B30.86861.735123.47246.94493.88987.771975.53951.17902.115804

在这里插入图片描述

对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。

二、Pyaudio

我们可以使用Python自带的标准库wave。
但实际我并不推荐使用wave,用soundfile, librosa和pydub之类的第三方库会方便和强大得多

初衷 语音识别领域对音频文件进行频谱分析是一项基本的数据处理过程,同时也为后续的特征分析准备数据。

前驱知识
Python需要使用的相关库

wave
https://docs.python.org/3/library/wave.html
pyaudio
http://people.csail.mit.edu/hubert/pyaudio/
numpy
https://www.runoob.com/numpy/numpy-tutorial.html
pylab
https://www.programcreek.com/python/example/2345/pylab.title
音频帧概率详解
1.采样率(Sample Rate):每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。一般音乐CD的采样率是44100Hz,所以视频编码中的音频采样率保持在这个级别就完全足够了,通常视频转换器也将这个采样率作为默认设置。
2.帧率(Frame rate):是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second,简称:FPS)或“赫兹”(Hz)。
3.码率(Bit Rate):指视频或音频文件在单位时间内使用的数据流量,该参数的单位通常是Kbps,也就是千比特每秒。通常2000kbps~3000kbps就已经足以将画质效果表现到极致了。码率参数与视频文件最终体积大小有直接性的关系
4.正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质

背景知识:
(一个AAC原始帧包含一段时间内1024个采样及相关数据)
分析:
1.AAC
音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)
一帧 1024个 sample。采样率 Samplerate 44.1KHz,每秒44100个sample, 所以根据公式 音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率
当前AAC一帧的播放时间是= 1024*1000/44100= 22.32ms(单位为ms)
2.MP3
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000 / sample_rate
例如:sample_rate = 44100HZ时,计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。
3.H264
视频的播放时间跟帧率有关:
frame_duration = 1000/帧率(fps)
例如:fps = 25.00 ,计算出来的时常为40ms,这就是同行所说的40ms一帧视频数据。

python"># 打开提前准备的WAV文档,文件路径根据需要做修改wf = wave.open("文档路径", "rb")# 创建PyAudio对象
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True
nframes = wf.getnframes()
framerate = wf.getframerate()# 读取完整的帧数据到str_data中,这是一个string类型的数据
str_data = wf.readframes(nframes)
wf.close()# 将音频波形数据转换为数组
# A new1-D array initialized from raw binary ortext data in a string.
wave_data = numpy.fromstring(str_data, dtype=numpy.short)# 将wave_data数组改为2列,行数自动匹配。在修改shape的属性时,需使得数组的总长度不变。
wave_data.shape = -1,2# 将数组转置
wave_data = wave_data.T
#time 也是一个数组,与wave_data[0]或wave_data[1]配对形成系列点坐标
#time = numpy.arange(0,nframes)*(1.0/framerate)# 绘制波形图
#pylab.plot(time, wave_data[0])
#pylab.subplot(212)
#pylab.plot(time, wave_data[1], c="g")
#pylab.xlabel("time (seconds)")
#pylab.show()# 采样点数,修改采样点数和起始位置进行不同位置和长度的音频波形分析
N=44100
start=0 #开始采样位置
df = framerate/(N-1) # 分辨率
freq = [df*n for n in range(0,N)] #N个元素
wave_data2=wave_data[0][start:start+N]
c=numpy.fft.fft(wave_data2)*2/N# 常规显示采样频率一半的频谱
d=int(len(c)/2)# 仅显示频率在4000以下的频谱
while freq[d]>4000:
d=10
pylab.plot(freq[:d-1],abs(c[:d-1]),'r')
pylab.show()

http://www.ppmy.cn/news/1519953.html

相关文章

Linux驱动(三):字符设备驱动之杂项

目录 一、Linux设备分类二、设备号与字符设备的编码方式1.设备号2.字符设备的编码方式 三、杂项字符设备驱动的初级编写 一、Linux设备分类 Linux下一切皆文件&#xff0c;所有的硬件设备在Linux应用层中都会被抽象成文件&#xff0c;所有对硬件设备的操作到应用层中&#xff0…

1004.最大连续1的个数Ⅲ

1.题目描述 给定一个二进制数组 nums 和一个整数 k&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1,0,0,0,1,1,1,1,0], K 2 输出&#xff1a;6 解释&#xff1a;[1,1,1,0,0,1,1,1,1,1,1…

我不是非酋之-天空概率

最近入坑了dnf手游&#xff0c;染上了合天空&#xff0c;大黑蛋子一个&#xff0c;突发奇想&#xff0c;模拟下合天空概率&#xff0c;看看是否真的有20%。 梳理代码逻辑如下&#xff1a; 不考虑礼包和其他东西 条件&#xff1a; 合成概率20%&#xff0c;每次需要2个装扮和一个…

改进YOLO的群养猪行为识别算法研究及部署(小程序-网站平台-pyqt)

概述 群养猪的运动信息和行为信息与其健康状况息息相关&#xff0c;但人工巡视费时费力&#xff0c;本实验提出采用行为识别算法于群养猪的养殖管理中&#xff0c;识别群养猪drink&#xff08;饮水&#xff09;、stand&#xff08;站立&#xff09;和lie&#xff08;躺卧&#…

论tomcat线程池和spring封装的线程池

Tomcat 中的线程池是什么&#xff1f; 内部线程池&#xff1a;Tomcat 确实有一个内部的线程池&#xff0c;用于处理 HTTP 请求&#xff0c;通常是org.apache.tomcat.util.threads.ThreadPoolExecutor 类的实例。这个线程池专门用于处理进入的 HTTP 请求和发送响应。可以通过 T…

【C++】手动实现String类的封装(分文件编译)

实现了String类的大部分封装&#xff0c;采用分文件编译 //mystring.h #ifndef MYSTRING_H #define MYSTRING_H#include <iostream> #include <cstring> using namespace std;class myString { private:char *str; //定义一个字符串int size; //记录字符串…

线性代数 第五讲:线性方程组_齐次线性方程组_非齐次线性方程组_公共解同解方程组_详解

线性方程组 文章目录 线性方程组1.齐次线性方程组的求解1.1 核心要义1.2 基础解系与线性无关的解向量的个数1.3 计算使用举例 2. 非齐次线性方程的求解2.1 非齐次线性方程解的判定2.2 非齐次线性方程解的结构2.3 计算使用举例 3.公共解与同解3.1 两个方程组的公共解3.2 同解方程…

鸿蒙界面开发(五):相对布局

相对布局RelativeContainer 相对布局的容器&#xff0c;支持容器内部的子元素设置相对位置关系&#xff0c;适用于界面复杂场景的情况&#xff0c;对多个子组件进行对齐和排列。子元素支持指定兄弟或父元素作为锚点&#xff0c;基于锚点做相对位置布局。 锚点&#xff1a;通过…

RK3568 Android 11 蓝牙BluetoothA2dpSink 获取用于生成频谱的PCM

Android 中的 A2DP Sink A2DP Sink 在 Android 系统中主要用于 接收 其他蓝牙设备&#xff08;如手机、平板、电脑等&#xff09;发送过来的 高质量的立体声音频。简单来说&#xff0c;它让你的 Android 设备可以充当一个 蓝牙音箱 或 耳机 的角色。 核心功能&#xff1a; 接…

vue3 监听

watch &#xff08;1&#xff09;监听ref 状态的变化 const num ref(1) watch(num,(newValue,oldValue)>{console.log(newValue,oldValue);//2,1 }) setTimeout(()>{num.value },500)&#xff08;2&#xff09;computed const num ref(1); const double computed((…

惠中科技光伏清洗剂:绿色清洁,引领光伏行业新潮流

在当今全球能源转型的大潮中&#xff0c;光伏产业作为绿色能源的重要组成部分&#xff0c;正以前所未有的速度蓬勃发展。然而&#xff0c;随着光伏板在户外环境的长时间暴露&#xff0c;其表面不可避免地会积累灰尘、鸟粪、油污等污染物&#xff0c;严重影响光伏板的透光率和发…

Gorm--Scan

在 Gorm 中&#xff0c;Scan 是一个用于将查询结果映射到自定义结构体或变量的函数。与 Find 或 First 不同&#xff0c;Scan 允许你将查询结果存储到与数据库模型不完全匹配的结构体中。它特别适合用于自定义查询结果或联合查询的场景。 type Result struct {Name stringEma…

#单片机基础 笔记二

SPI中断 1.SPI总线协议 1.1协议介绍 SPI接口是Motorola &#xff08;motorola | Smartphones, Accessories & Smart Home Devices&#xff09;首先提出的全双工三线/四线同步串行外围接口采用主从模式&#xff08;Master Slave&#xff09;架构。 时钟由Master控制&#xf…

ELK学习笔记——如何给Kibana新增用户和角色

Kibana新增用户和角色 首先用超管账号登录上Kibana&#xff0c;按照下面步骤操作 1、创建角色 按图操作 2、创建用户 按图操作 3、给用户分配角色 至此&#xff0c;角色和用户绑定成功&#xff1b; 最后&#xff0c;可以退出管理员账号&#xff0c;登录这个新…

github私有仓库通过action部署hexo到公开仓库

github私有仓库通过action部署hexo到公开仓库 有一段时间一直将博客md文件直接放到公开仓库然后通过工作流action创建一个gh-page分支&#xff0c;来实现部署 但是这样做有一个问题&#xff0c;如果你的源文件&#xff0c;或者配置文件中有涉及变量&#xff0c;或者密钥key&a…

Linux-vim

文章目录 vi和vimvim的基本概念vim的基本操作vim正常模式命令集插入模式从插入模式切换为命令模式移动光标删除文字复制替换撤销上一次操作更改跳至指定的行 vim末行模式命令集列出行号跳到文件中的某一行查找字符保存文件推出vim vi和vim vi/vim的区别简单点来说&#xff0c;…

Linux C 内核编程 /proc 编程例子

直接上代码 proc_demo.c内核版本&#xff1a; 5.4.0-150-generic #include <linux/module.h> #include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/slab.h>s…

threading.local的使用

python中的threading.local对象 在Python中&#xff0c;使用threading.local对象的意义在于为每个线程提供了一种安全地存储和访问线程局部变量的方式。这种机制对于多线程编程特别有用&#xff0c;因为它可以帮助开发者避免一些常见的多线程编程问题&#xff0c;如数据竞争、…

技术周刊 | Rspack 1.0、v0 支持 Vue、2024 年度编程语言排行榜、Ideogram 2.0、从 0 实现一个 React

大家好&#xff0c;我是童欧巴&#xff0c;欢迎来到第 126 期技术周刊。 资讯 Rspack 1.0 Rspack 1.0 正式发布&#xff0c;作为一款基于 Rust 的高性能 JavaScript 打包工具&#xff0c;它兼容 webpack API 和生态&#xff0c;提供了显著提升的构建性能。1.0 版本在性能、兼…

第三章:实时流数据处理与分析

目录 3.1 流处理框架深入解析与实战 Flink与Kafka Streams的性能对比&#xff1a;事件驱动架构的代码实现 1. Apache Flink&#xff1a;流处理的“性能怪兽” 2. Kafka Streams&#xff1a;轻量级、低延迟的流式处理框架 实时异常检测与报警系统&#xff1a;结合Flink CEP…