Воспроизведение потоков ADPCM с Pygame

У меня есть несколько сырых сжатых аудиопотоков ADPCM, и я хочу воспроизвести их с помощью pygame, но, насколько я знаю, это невозможно с помощью pygame. Как мне распаковать их с помощью python в обычные потоки PCM (или что-то еще, что может воспроизводить pygame), а затем воспроизвести их с помощью pygame?

Я уже попробовал модуль audioop, так как в нем есть что-то, что преобразует ADPCM в линейные потоки, но я не знаю, что такое линейные потоки и как использовать функцию, которая их преобразует.

1 ответ

Решение

Я уже попробовал модуль 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, вы не идете сюда для аудиофильского звука.

Другие вопросы по тегам