python处理原始音频数据
文章目录
- 基础知识
- 转换函数
- 片段特征函数
- 片段操作
audioop是python标准库中用于处理原始音频数据的模块,封装了一些便捷的编码转换函数。
基础知识
PCM(pulse code modulation),即脉冲编码调制,是将模拟信号转为数字信号的一种编码系统。而模数转换主要分两步,首先对连续的模拟信号进行采样,然后把采样得到的数据转化为数值,即量化。
设xxx为输入信号,F(x)F(x)F(x)为量化后的信号,则F(x)F(x)F(x)既可以是线性的,也可以是非线性的。在audioop
中,主要提供三种编码支持,分别是a-Law,μ-Law以及ADPCM。
其中,μ律(μ -Law)压扩主要用在北美和日本等地,其表达形式为
Fμ=sgn(x)ln(1+μ∣x∣)ln(1+μ)F_\mu=\operatorname{sgn}(x)\frac{\ln(1+\mu|x|)}{\ln(1+\mu)} Fμ=sgn(x)ln(1+μ)ln(1+μ∣x∣)
其中sgn(x)\operatorname{sgn}(x)sgn(x)是符号函数,其表达式为
sgn(x)={−1x<00x=01x>0\operatorname{sgn}(x)=\left\{\begin{aligned} &-1&x<0\\ &0&x=0\\ &1&x>0\\ \end{aligned}\right. sgn(x)=⎩⎪⎨⎪⎧−101x<0x=0x>0
由于其输入输出为对数关系,故又称对数PCM,其中μ\muμ为压缩系数,在CCITT建议中取255。
在中国和欧洲主要实用的编码方式为A-Law,其表达式为
FA(x)={Ax1+lnA0⩽∣x∣⩽1Asgn(x)1+ln(A∣x∣)1+lnA1A⩽∣x∣⩽1F_A(x)= \left\{\begin{aligned} &\frac{Ax}{1+\ln A}&0\leqslant|x|\leqslant\frac{1}{A}\\ &\operatorname{sgn}(x)\frac{1+\ln(A|x|)}{1+\ln A}&\frac{1}{A}\leqslant|x|\leqslant1 \end{aligned}\right. FA(x)=⎩⎪⎪⎨⎪⎪⎧1+lnAAxsgn(x)1+lnA1+ln(A∣x∣)0⩽∣x∣⩽A1A1⩽∣x∣⩽1
其中AAA为压缩系数,在G.726标准中建议87.56。
ADPCM(Adaptive Differential PCM),即自适应差分PCM。
由于模拟信号的连续性,一般来说相邻时间单位的信号往往具有较高的线性度,甚至彼此相差无几,从而可以被高效率的压缩。然而,也存在跳跃幅度较大的信号,如果完全以缓变为原则,那么必然会丢失这部分数据。为了均衡这种差异,就需要进行自适应量化。
audioop中支持的Intel/DVI ADPCM算法可以在网上找到,但是信息并不多而且都很老旧,貌似不太重要的样子,甚至知网都搜不到,所以这里就不详细解读了。
转换函数
audioop提供了ADPCM、A-Law和μ-Law和线性采样之间的转换函数
采样 | ADPCM | A-Law | μ-Law |
---|---|---|---|
lin2lin
|
lin2adpcm
|
lin2alaw
|
lin2ulaw
|
adpcm2lin
|
alaw2lin
|
ulaw2lin
|
其中,与A-Law和μ-Law有关的转换函数的输入参数为(fragment, width)
,分别代表待处理片段和位宽;adpcm
则会多一个state
元组作为第三个参数,表示编码器状态。
lin2lin
是将线性片段在1、2、3 和 4 字节格式之间转换的函数,其输入参数为(fragment, width, newwidth)
。
下面新建一些数据来测试一下编码转换函数,
#下面代码来自于test_audioop.py
import audioop
import sys
import unittestpack = lambda width, data :b''.join(v.to_bytes(width, sys.byteorder, signed=True) for v in data)packs = {w: (lambda *data, width=w: pack(width, data)) for w in (1, 2, 3, 4)}unpack = lambda width, data: [int.from_bytes(data[i: i + width], sys.byteorder, signed=True)for i in range(0, len(data), width)]datas = {1: b'\x00\x12\x45\xbb\x7f\x80\xff',2: packs[2](0, 0x1234, 0x4567, -0x4567, 0x7fff, -0x8000, -1),3: packs[3](0, 0x123456, 0x456789, -0x456789, 0x7fffff, -0x800000, -1),4: packs[4](0, 0x12345678, 0x456789ab, -0x456789ab,0x7fffffff, -0x80000000, -1),
}
则datas
的值为
>>> for key in datas : print(datas[key])
...
b'\x00\x12E\xbb\x7f\x80\xff'
b'\x00\x004\x12gE\x99\xba\xff\x7f\x00\x80\xff\xff'
b'\x00\x00\x00V4\x12\x89gEw\x98\xba\xff\xff\x7f\x00\x00\x80\xff\xff\xff'
b'\x00\x00\x00\x00xV4\x12\xab\x89gEUv\x98\xba\xff\xff\xff\x7f\x00\x00\x00\x80\xff\xff\xff\xff'
>
则其转换函数测试如下
>>> datas[1]
b'\x00\x12E\xbb\x7f\x80\xff' #将要处理的1位线性码
>>> unpack(1,datas[1])
[0, 18, 69, -69, 127, -128, -1] #转为整型
# 将1字节线性码转为2字节线性码
>>> datas1_2 = audioop.lin2lin(datas[1], 1, 2)
>>> print(datas1_2)
b'\x00\x00\x00\x12\x00E\x00\xbb\x00\x7f\x00\x80\x00\xff'
>>> unpack(2,datas1_2) #转为整型,其值为datas[1]*256
[0, 4608, 17664, -17664, 32512, -32768, -256]
# 将1字节线性码转为1字节u-Law码
>>> datas1_u = audioop.lin2ulaw(datas[1], 1)
>>> unpack(1,datas1_u) #转为整型,这个数和u-law的公式对不上,可能是其他算法
[-1, -83, -114, 14, -128, 0, 103]
片段特征函数
下表中函数的输入为(fragment, width)
,分别代表待统计片段和位宽。
返回值 | |
---|---|
avg
|
片段采样值的均值 |
avgpp
|
片段采样值的平均峰峰值 |
max
|
片段采样值的最大绝对值 |
maxpp
|
声音片段中的最大峰峰值 |
minmax
|
由片段采样值中最小和最大值组成的元组 |
rms
|
片段的均方根 |
cross
|
片段穿越零点的次数 |
getsample(fragment, width, index)
,顾名思义用于采样,返回段中采样值索引index
的值。
findfactor(fragment, reference)
,返回一个系数F使得rms(add(fragment, mul(reference, -F)))
最小,即返回的系数乘以reference
后与fragment
最匹配。两个片段都应包含 2 字节宽的采样。
findfit(fragment, reference)
,尽可能尝试让 reference 匹配 fragment 的一部分。
findmax(fragment, length)
,在fragment
中搜索所有长度为length
的采样切片中,能量最大的那一个切片,即返回 i 使得 rms(fragment[i*2:(i+length)*2]) 最大。
片段操作
其返回值均为片段,下表的参数中,f
表示fragment
,w
表示width
,L
表示lfactor
,R
表示rfactor
返回值 | |
---|---|
byteswap(f, w)
|
按字节交换片段中的采样值后返回 |
reverse(f, w)
|
将片段中的采样值反转后返回 |
mul(f, w, factor)
|
fragment 中的采样值×浮点数factor ,溢出则截断
|
add(f1, f2, w)
|
两个fragment 的采样值相加
|
tostereo(f, w, L, R)
|
单声道转立体声,左声道乘以L,右声道是乘以R |
tomono(f, w, L, R)
|
立体声转单声道,左通道乘以L,右通道乘以R,然后相加 |
bias(f, w, bias)
|
fragment 中的采样值+bias
|
audioop.ratecv(f, w, nchannels, inrate, outrate, state[, weightA[, weightB]])
可用于转换输入片段的帧速率,其中
state
为元组,表示转换器状态weightA
和weightB
是简单数字滤波器的参数,默认为 1 和 0。
python处理原始音频数据相关推荐
- 如何利用python处理原始音频数据
特别鸣谢以下更多python教程请到友情连接: 菜鸟教程https://www.piaodoo.com 初中毕业读什么技校 http://cntkd.net 茂名一技http://www.enechn ...
- 使用Sinc卷积从原始音频数据进行轻量级的端到端语音识别
论文: Lightweight End-to-End Speech Recognition from Raw Audio Data Using Sinc-Convolutions 摘要: 许多端到端自 ...
- Python采集喜马拉雅音频数据详解
前言 喜马拉雅是专业的音频分享平台,汇集了有声小说,有声读物,有声书,FM电台,儿童睡前故事,相声小品,鬼故事等数亿条音频,我最喜欢听民间故事和德云社相声集,你呢? 今天带大家爬取喜马拉雅音频数据,一 ...
- python获取mp3音频数据,python 读取音频文件的详细信息
有一项测试的需求是判断录像是否和预期一致,检查项是:分辨率.录像时长等内容 文件的详细信息.png os模块有一个stat()方法 st_mode: inode 保护模式 st_ino: inode ...
- python批处理原始核磁数据用于DPABI
师姐给了一个任务,要我把核磁室导出来的数据自动化处理到能直接丢进去DPABI,这对我来说简直是小事一桩嘛. 原始文件夹结构: Patients --> FunRaw --> sub001 ...
- python获取mp3音频数据_详解python进行mp3格式判断 python怎么读取mp3文件
python中哪个库有em算法 EM算法初稿2016-4-28 初始化三个一维的高斯分布 from numpy import * import numpy as np import matplotli ...
- 利用qt播放音频数据
今天分享一下如何利用qt的接口来播放pcm的原始音频数据. 首先需要准备好一段pcm的原始音频数据,这边可以通过ffmpeg的命令将mp4视频格式中的音频提取出来并按照pcm的格式进行保存. 命令为: ...
- 剪切音频文件是处理音频数据
剪切音频文件是处理音频数据的最基本功能之一 pydub库使之变得超级简单.就像关于裁剪和调整图片的那篇文章一样,这个程序能够进入一级Python类别的唯一原因是使用了一个外部库. 在这篇文章中,我们将 ...
- 《android多媒体api》之AudioTrack原始音频pcm播放api
<android多媒体api>系列是整合梳理android开发中经常用到的媒体相关api:多媒体开发主要内容有音频.视频录制播放.摄像头操作.录制操作.流媒体.直播.推流.拉流等方面:最近 ...
最新文章
- 网络学习笔记—计算机网络基础
- 对抗新冠也用「梯度下降」,进化生物学家靠这个预测病毒进化方向
- 编程方法学26:介绍Java标准库
- 1MySQL是面向对象型数据库_数据库及MySQL基础(1)
- 2015c语言9月答案,2015年9月计算机二级C语言预测题答案
- SAP中的默认帐户与密码
- map函数python返回值,Python中map函数使用
- 程序员专属段子集锦 7/10
- 点云处理软件开发进度
- Java数据结构与算法(二) 简单排序
- 如何关闭dell inspiron n4010的内置麦克
- java+整合handwrite_解决java.lang.UnsatisfiedLinkError: JNI_ERR returned from JNI_OnLoad
- 计算机音乐演奏jojo,【FF14】诗人演奏用 il vento d'oro(动画《JOJO的奇妙冒险 黄金之风》插曲)...
- Java 二维码及条形码处理
- 【SAP】进项税的配置与传输
- 网络舆情风险和危机监测解决方案
- 前端开发的 学php吗,web前端开发难学吗
- 【实习之路】在广州欢聚时代入职的第一天
- 王杰与宣萱合作lt;老婆大人gt; 获封两个第一(图)
- 汽车电子点火控制系统