使用 Pygame 播放 ADPCM 流



我有一些原始的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 时,您不会在这里获得发烧友的声音。

相关内容

  • 没有找到相关文章

最新更新