21.1. audioop —处理原始音频数据

audioop模块包含一些有用的声音片段操作。它对声音片段进行操作,这些片段由存储在 Python 字符串中的 8、16 或 32 位宽的有符号整数 samples 组成。此格式与alsunaudiodev模块使用的格式相同。除非另有说明,否则所有标量项均为整数。

该模块支持 a-LAW,u-LAW 和 Intel/DVI ADPCM 编码。

一些更复杂的操作仅获取 16 位 samples,否则 samples 大小(以字节为单位)始终是该操作的参数。

该模块定义以下变量和函数:

2.5 版的新Function。

该例程花费的时间与len(fragment)成正比。

该例程所花费的时间与len(fragment)成正比。

2.5 版的新Function。

Note

在某些音频格式(例如.WAV 文件)中,对 16 位和 32 位 samples 进行了签名,但对 8 位 samples 进行了无符号化。因此,当将这些格式转换为 8 位宽的 samples 时,还需要在结果中添加 128:

new_frames = audioop.lin2lin(frames, old_width, 1)
new_frames = audioop.bias(new_frames, 1, 128)

相反,当从 8 位转换为 16 位或 32 位宽度的 samples 时,必须应用相同的内容。

这是音频 signal 中功率的度量。

请注意,诸如mul()max()之类的操作在单声道和立体声片段之间没有区别,即所有 samples 均被视为相等。如果存在问题,则应先将立体声片段分为两个单声道片段,然后再进行重组。这是如何执行此操作的示例:

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 编码器构建网络数据包,并且希望协议是 Stateless 的(即能够容忍数据包丢失),则不仅应该传输数据,还应该传输状态。请注意,您应该将* initial *状态(传递给lin2adpcm()的状态)发送给解码器,而不是finally状态(由编码器返回)。如果要使用struct.Struct将状态存储为二进制,则可以用 16 位编码第一个元素(预测值),而用 8 位编码第二个元素(增量索引)。

从未try过将 ADPCM 编码器与其他 ADPCM 编码器对立,而仅针对自身。我很可能误解了标准,在这种情况下,它们将无法与相应标准互操作。

find*()例程乍一看可能会有些有趣。它们主要是为了进行回声消除。一种合理的快速方法是从输出 samples 中选取能量最高的片段,将其放置在 Importingsamples 中,然后从 Importingsamples 中减去整个输出 samples:

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)
首页