使用Pygame播放ADPCM流

时间:2013-10-02 19:07:31

标签: python audio stream pygame adpcm

我有一些原始的ADPCM压缩音频流,我想用pygame播放它们,但据我所知,这与pygame不可能。我如何用python将它们解压缩到普通的PCM流(或pygame可以播放的其他东西),然后用pygame播放它们?

我已经尝试过audioop模块,因为它有一些可以将ADPCM转换为线性流但我既不知道线性流也不知道如何使用转换它们的函数。

1 个答案:

答案 0 :(得分:4)

  

我已经尝试过audioop模块,因为它有一些可以将ADPCM转换为线性流但我既不知道线性流也不知道如何使用转换它们的函数。

简短版本:“线性”是你想要的。*所以,你想要的功能是adpcm2lin


你如何使用它?

audioop中的几乎所有内容都以相同的方式工作:遍历帧,并在每个帧上调用一个函数。如果您的输入数据具有某些固有的帧大小,例如当您从MP3文件(使用外部库)读取时,或者您的输出库需要某些特定的帧大小时,您对如何确定帧有一定的限制。但是当你处理原始PCM格式时,框架可以是你想要的任何尺寸,从单个样本到整个文件。**

为简单起见,我们先做整个文件:

with open('spam.adpcm', 'rb') as f:
    adpcm = f.read()
pcm, _ = audioop.adpcm2lin(adpcm, 2, None)

如果您的adpcm文件太大而无法加载到内存中并一次处理所有文件,则需要跟踪state,所以:

with open('spam.adpcm', 'rb') as f:
    state = None
    while True:
        adpcm = f.read(BLOCKSIZE)
        if not adpcm:
            return
        pcm, state = audioop.adpcm2lin(adpcm, 2, state)
        yield pcm

当然我假设你不需要转换采样率或做任何其他事情。如果您这样做,任何此类转换都应在ADPCM解压缩之后进行。***


*长版本:“线性”表示样本直接编码,而不是通过其他算法映射。例如,如果您有一个16位的A-to-D,并且您将音频保存在8位线性PCM文件中,那么您只需保存每个样本的前8位。这给你一个非常动态的范围,所以更安静的声音在噪音中丢失。有各种压缩扩展算法可以为相同数量的位提供更宽的动态范围(当然,代价是丢失其他地方的其他信息);有关它们如何工作的详细信息,请参阅μ-law算法。但如果你能保持16位,线性就好了。

**实际上,使用4位原始ADPCM,你真的不能做一个样本......但你可以做2个样本,这已经足够接近了。

***如果你真的很挑剔,你可能想先转换为32位,然后再做工作,然后转换回16位以避免累积损失。但是当你开始使用4位ADPCM时,你不会在这里听到发烧友的声音。