audioio
либо audiopwmio
,
реализующий фоновый звук родными для платы способами. К сожалению,
для Meowbit (и вообще для плат на основе STM32)
не реализован ни тот ни другой модуль; но в opensource-проекте это
дело поправимое :)Найдите пасхалку в фото
Прежде всего: почему для проигрывания звука есть два разных модуля с полностью одинаковыми API, и на разных платах поддерживается либо тот, либо другой?
Вот как в аудиоредакторе (например Audacity) выглядит секунды обычного (16-битного)
WAV-файлa:
Значение плавно меняется в пределах примерно от 0.2 до +0.2 условной единицы. Если таким же образом менять напряжение, подаваемое на электродинамический громкоговоритель, то так же плавно будет колебаться мембрана примерно от 0.2 своего максимально возможного отклонения в одну сторону, до 0.2 отклонения в другую сторону. Модуль
audioio
реализует именно такое проигрывание
звука через
ЦАП плавно меняет напряжение на выводе, соединённом с
динамиком.Но в Meowbit вместо динамика стоит дешёвая пьезопищалка, неспособная отклонять мембрану в промежуточные положения: она из одного крайнего положения очень быстро переходит в другое крайнее, и остаётся там до следующего перехода. Это можно представить как звук с разрешением в один бит на сэмпл:
Таким способом невозможно передавать изменение громкости звука, но теоретически возможно передать все имеющиеся в нём гармоники если параллельно с 32768-кратным понижением разрешения увеличить во столько же раз (т.е. до сотен мегагерц) частоту дискретизации. Маловероятно, что мембрана пьезопищалки сможет колебаться с такой частотой; но это можно использовать и в свою пользу если научиться переключать напряжение на пищалке, когда мембрана на полпути, то можно издавать звуки промежуточной громкости! Поиск по патентам подтверждает, что люди действительно исследуют возможности использовать пьезопищалку таким образом. Мы в эти дебри углубляться не будем, и оставим обычную для WAV частоту дискретизации в десятки килогерц. Для музыки, где основные гармоники в районе килогерца, этого достаточно; речь, однако, превращается в едва разборчивый шум. Можете сравнить, как воспринимается использованный мной восьмисекундный образец звука, воспроизведённый на однобитной пьезопищалке: вначале оригинал, затем однобитная версия, затем запись Meowbit-а микрофоном.
Модуль
audiopwmio
реализует проигрывание звука через
цифровой вывод посредством
ШИМ: однобитная аудиозапись превращается в последовательность
задержек между переключениемвывода на противоположное значение.
Итак, общий план реализации
audiopwmio
для Meowbit
таков:- Переводим переданную пользователем аудиозапись в ШИМ-формат (список задержек между переключениями);
- В обработчике прерывания от таймера переключаем вывод и
настраиваем таймер на задержку до следующего переключения. Этот код
можно с минимальными изменениями позаимствовать из стандартного
модуля
pulseio
, реализующего в точности то, что нам нужно переключение вывода в соответствии с переданным списком задержек но не позволяющего коду на Python выполняться параллельно с переключением.
Не сразу было очевидно, что надо позаботиться ещё об одном аспекте реализации буферизации аудио. Мой тестовый восьмисекундный образец занимает 8220502 340 КБ это втрое больше, чем всё ОЗУ Meowbit; следовательно, загружать его в память придётся по кускам. Стандартная реализация
audiocore.WaveFile
загружает
WAV-файл кусочками по 256 байт, что соответствует 128 сэмплам или
5.8 мс времени проигрывания. Это значит, что в среднем каждые 5.8
мс audiopwmio
должен будет запрашивать повторное
наполнение буфера; нет выхода, кроме как разместить этот вызов в
том же самом обработчике прерывания от таймера иначе перерисовка
экрана может задержать наполнение буфера на добрую сотню
миллисекунд. Проблему это, однако, не решает до конца: что
произойдёт, если прерывание от таймера случится во время
перерисовки экрана? Экран Meowbit подключён через
шину SPI, флеш-диск через неё же, значит обращение ко флешу во
время перерисовки экрана всё равно невозможно!В результате получилась реализация
audiopwmio
,
способная воспроизводить аудиозаписи из памяти (или процедурно
генерируемые) в максимально достижимом на Meowbit качестве; но
аудиозаписи из файлов воспроизводятся только при отсутствии
одновременных с этим обращений к экрану и ко флешу. Для звукового
сопровождения несложных игр этого вполне хватит. PR с моей
реализацией уже больше недели дожидается ревью, и когда
audiopwmio
для Meowbit появится в официальной версии
CircuitPython неизвестно; но это не мешает любым желающим
самостоятельно скомпилировать себе CircuitPython с моей
добавкой.