audioop
audioop — Manipulate raw audio data
该audioop
模块包含对声音片段的一些有用操作。它对由8,16或32位宽的有符号整数样本组成的声音片段进行操作,并以Python字符串存储。这与al
和sunaudiodev
模块使用的格式相同。所有标量项都是整数,除非另有规定。
该模块提供对a-LAW,u-LAW和Intel / DVI ADPCM编码的支持。
一些更复杂的操作只需要16位采样,否则采样大小(以字节为单位)始终是操作的参数。
该模块定义了以下变量和功能:
exception audioop.error
所有错误都会引发此异常,例如每个样本的未知字节数等等。
audioop.add(fragment1, fragment2, width)
返回一个片段,它是作为参数传递的两个样本的添加。宽度
是以字节为单位的采样宽度
1
,2
或者是4
。两个片段应具有相同的长度。溢出时截断样本。
audioop.adpcm2lin(adpcmfragment, width, state)
将Intel / DVI ADPCM编码片段解码为线性片段。有关lin2adpcm()
ADPCM编码的详细信息,请参阅说明。返回(sample, newstate)
样本宽度
指定宽度
的元组。
audioop.alaw2lin(fragment, width)
将a-LAW编码中的声音片段转换为线性编码的声音片段。a-LAW编码总是使用8位样本,因此宽度
仅指此处输出片段的样本宽度
。
2.5版本中的新功能。
audioop.avg(fragment, width)
返回片段中所有样本的平均值。
audioop.avgpp(fragment, width)
返回片段中所有样本的平均峰 - 峰值。没有过滤完成,所以这个例程的用处是有问题的。
audioop.bias(fragment, width, bias)
返回一个片段,该片段是在每个样本中添加了偏差的原始片段。样品环绕在溢出情况下。
audioop.cross(fragment, width)
返回作为参数传递的片段中零交叉的数量。
audioop.findfactor(fragment, reference)
返回一个因子F
,使其rms(add(fragment, mul(reference, -F)))
最小化,也就是说,返回您应该乘以参考
的因子,使其尽可能匹配以便片段化
。这些片段都应该包含2个字节的样本。
这个程序所用的时间与成正比len(fragment)
。
audioop.findfit(fragment, reference)
尝试尽可能将参考
与片段
的一部分(应该是更长的片段
)进行匹配。这是(从概念上)通过从片段
中取出片段
来完成的,findfactor()
用于计算最佳匹配并最小化结果。这些片段
都应该包含2个字节的样本。返回一个元组(offset, factor)
,其中偏移量
是(整数)偏移量
到最佳匹配开始的片段
,factor
是(浮点)因子findfactor()
。
audioop.findmax(fragment, length)
搜索具有最大能量的长度
长度
采样片段
(不是字节!),即返回i
,其最大值。这些片段
都应该包含2个字节的样本。rms(fragment[i*2:(i+length)*2])
该程序需要的时间与成比例len(fragment)
。
audioop.getsample(fragment, width, index)
从片段中返回样本索引
的值。
audioop.lin2adpcm(fragment, width, state)
将采样转换为4位Intel / DVI ADPCM编码。ADPCM编码是一种自适应编码方案,其中每个4位数是一个样本与下一个样本之间的差异,除以(变化)步骤。英特尔/ DVI ADPCM算法已被IMA选用,因此它很可能成为标准。
state
是一个包含编码器状态
的元组。编码器返回一个元组(adpcmfrag, newstate)
,并且新状态
应该被传递给下一个lin2adpcm()
。在最初的调用中,None
可以作为状态
传递。adpcmfrag
是ADPCM编码的片段,每个字节包装2个4位值。
audioop.lin2alaw(fragment, width)
将音频片段中的样本转换为a-LAW编码,并将其作为Python字符串返回。a-LAW是一种音频编码格式,您只需使用8位样本即可获得约13位的动态范围。它由Sun音频硬件等使用。
2.5版本中的新功能。
audioop.lin2lin(fragment, width, newwidth)
在1,2和4字节格式之间转换采样。
注意
在某些音频格式(如.WAV文件)中,有16位和32位采样被签名,但8位采样未经签名。因此,当转换为这些格式的8位宽采样时,还需要将128添加到结果中:
new_frames = audioop.lin2lin(frames, old_width, 1)
new_frames = audioop.bias(new_frames, 1, 128)
相反,在从8位转换为16位或32位宽度采样时,必须应用相同的方法。
audioop.lin2ulaw(fragment, width)
将音频片段中的样本转换为u-LAW编码,并将其作为Python字符串返回。u-LAW是一种音频编码格式,您只需使用8位采样即可获得约14位的动态范围。它由Sun音频硬件等使用。
audioop.max(fragment, width)
返回片段中所有样本的绝对值
的最大值。
audioop.maxpp(fragment, width)
返回声音片段中的最大峰 - 峰值。
audioop.minmax(fragment, width)
返回由声音片段中所有样本的最小值和最大值组成的元组。
audioop.mul(fragment, width, factor)
返回原始片段中所有样本乘以浮点值因子的
片段。溢出时截断样本。
audioop.ratecv(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])
转换输入片段的帧频。
state
是包含转换器状态
的元组。转换器返回一个元组(newfragment, newstate)
,并且newstate
应该被传递给下一个调用ratecv()
。最初的呼叫应该None
作为状态
传递。
的weightA
和weightB
参数是一个简单的数字滤波器和默认参数以1
及0
分别。
audioop.reverse(fragment, width)
反转片段中的样本并返回修改后的片段。
audioop.rms(fragment, width)
返回片段的均方根,即sqrt(sum(S_i^2)/n)
。
这是衡量音频信号功率的指标。
audioop.tomono(fragment, width, lfactor, rfactor)
将立体声片段转换为单声道片段。左声道乘以lfactor
,右声道乘以rfactor,
然后再添加两个声道以提供单声道信号。
audioop.tostereo(fragment, width, lfactor, rfactor)
从单片段生成立体声片段。每对在立体声片段的样品被从样品单声道,由此左声道采样乘以计算lfactor
通过和右信道样本rfactor
。
audioop.ulaw2lin(fragment, width)
将u-LAW编码中的声音片段转换为线性编码的声音片段。u-LAW编码总是使用8位样本,因此宽度
仅指此处输出片段的样本宽度
。
请注意,诸如mul()
或max()
不区分单声道和立体声片段的操作,即所有样本均被视为相同。如果这是一个问题,立体声片段应该先被分成两个单声道片段,然后重新组合。这里是一个如何做到这一点的例子:
def mul_stereo(sample, width, lfactor, rfactor):
lsample = audioop.tomono(sample, width, 1, 0)
rsample = audioop.tomono(sample, width, 0, 1)
lsample = audioop.mul(lsample, width, lfactor)
rsample = audioop.mul(rsample, width, rfactor)
lsample = audioop.tostereo(lsample, width, 1, 0)
rsample = audioop.tostereo(rsample, width, 0, 1)
return audioop.add(lsample, rsample, width)
如果您使用ADPCM编码器来构建网络数据包,并且希望您的协议是无状态的(即能够承受数据包丢失),则不仅应该传输数据,还应该传输状态。请注意,您应该将初始
状态(传递给您的那个状态lin2adpcm()
)发送给解码器,而不是最终状态(由编码器返回)。如果要使用struct.Struct
以二进制形式存储状态,则可以将第一个元素(预测值)编码为16位,将第二个(delta索引)编码为8。
ADPCM编码器从未与其他ADPCM编码器一起使用过,仅针对他们自己。很可能是因为我错误地解释了标准,在这种情况下,他们将不能与各自的标准互操作。
这些find*()
例程一看起来可能有点有趣。它们主要是为了做回声消除。这样做的一个相当快速的方法是从输出采样中选出最有活力的一块,在输入采样中找到它,并从输入采样中减去整个输出采样:
def echocancel(outputdata, inputdata):
pos = audioop.findmax(outputdata, 800) # one tenth second
out_test = outputdata[pos*2:]
in_test = inputdata[pos*2:]
ipos, factor = audioop.findfit(in_test, out_test)
# Optional (for better cancellation):
# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
# out_test)
prefill = '\0'*(pos+ipos)*2
postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
return audioop.add(inputdata, outputdata, 2)