我有一些原始的ADPCM压缩音频流,我想用pygame播放它们,但据我所知,这在pygame上是不可能的。如何使用python将它们解压缩为普通的PCM流(或其他pygame可以播放的内容(,然后使用pygame播放它们?
我已经尝试了 audioop 模块,因为它有一些可以将 ADPCM 转换为线性流的东西,但我既不知道什么是线性流,也不知道如何使用转换它们的函数。
我已经尝试了 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 位。这为您提供了非常动态的范围,因此更安静的声音会迷失在噪音中。有各种压缩算法可以为相同数量的位提供更宽的动态范围(当然,代价是丢失其他地方的其他信息(;有关其工作原理的详细信息,请参阅 μ定律算法。但如果你能保持在16位,线性就可以了。
** 实际上,使用 4 位原始 ADPCM,您真的无法进行单个采样......但是你可以做 2 个样本,这已经足够接近了。
如果你真的很挑剔,你可能想先转换为 32 位,然后完成工作,然后再转换回 16 位以避免累积损失。但是,当您开始使用 4 位 ADPCM 时,您不会在这里获得发烧友的声音。