pythonaudiostreampygameadpcm

Play ADPCM streams with Pygame


I've got some raw ADPCM compressed audio streams and I want to play them with pygame, but as far as I know this isn't possible with pygame. How can I decompress them with python to normal PCM streams (or something else pygame can play) and then play them with pygame?

I already tried the audioop module as it has got something that converts ADPCM to linear streams but I neither know what linear streams are nor how to use the function that converts them.


Solution

  • I already tried the audioop module as it has got something that converts ADPCM to linear streams but I neither know what linear streams are nor how to use the function that converts them.

    The short version: "Linear" is what you want.* So, the function you want is adpcm2lin.


    How do you use it?

    Almost everything in audioop works the same way: you loop over frames, and call a function on each frame. If your input data has some inherent frame size, like when you're reading from an MP3 file (using an external library), or your output library demands some specific frame size, you're a bit constrained on how you determine your frames. But when you're dealing with raw PCM formats, the frames are whatever size you want, from a single sample to the whole file.**

    Let's do the whole file first, for simplicity:

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

    If your adpcm file is too big to load into memory and process all at once, you'll need to keep track of the state, so:

    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
    

    Of course I'm assuming that you don't need to convert the sample rate or do anything else. If you do, any such conversions should come after the ADPCM decompression.***


    * The long version: "Linear" means the samples are encoded directly, rather than mapped through another algorithm. For example, if you have a 16-bit A-to-D, and you save the audio in an 8-bit linear PCM file, you're just saving the top 8 bits of each sample. That gives you a very dynamic range, so quieter sounds get lost in the noise. There are various companding algorithms that give you a much wider dynamic range for the same number of bits (at the cost of losing other information elsewhere, of course); see μ-law algorithm for details on how they work. But if you can stay in 16 bits, linear is fine.

    ** Actually, with 4-bit raw ADPCM, you really can't do a single sample… but you can do 2 samples, which is close enough.

    *** If you're really picky, you might want to convert to 32-bit first, then do the work, then convert back to 16-bit to avoid accumulating losses. But when you're starting with 4-bit ADPCM, you aren't going for audiophile sound here.