当前位置: 首页 > news >正文

Python对音频进行频谱分析

文章目录

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

一、储备函数

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

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一帧视频数据。

# 打开提前准备的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.mrgr.cn/news/18472.html

相关文章:

  • 美团代付支持多模板全开源多种支付通道 多模版三合一源码附教程
  • 【算法】-贪心算法
  • Django 第十三课 -- Form 组件
  • 基于yolov8的路面垃圾检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
  • SUSE Linux下编译Nginx报错:recipe for target ‘install‘ failed
  • 团队动力之社会比较理论
  • 推荐大模型面临的严峻挑战
  • XSLT 元素
  • Java Full GC 的常见原因及优化策略
  • 大小驼峰命名规则
  • C语言 | Leetcode C语言题解之第392题判断子序列
  • c++ unordered_map的用法
  • 问:关于内部类,知道这些就够了~
  • 算法打卡 Day25(二叉树)-修剪二叉搜索树 + 将有序数组转换为二叉搜索树 + 把二叉搜索树转换为累加树
  • 【Linux】Linux命令行大冒险:寻找、搜索与压缩的神奇之旅
  • 带你0到1之QT编程:二、一举击碎QT常用数据类型
  • 幂等的通用实现方案
  • 前端算法面试题1--栈、队列、链表、字典与哈希表
  • Golang | Leetcode Golang题解之第391题完美矩形
  • 【hot100篇-python刷题记录】【电话号码的字母组合】