Теперь же мой самодельный аудиодвижок научился выводить звук.

Я реализовал это засчет низкоуровневых API waveOut/waveIn - первому API для вывода и ввода аудио, который появился ещё во времена Windows 3.0 и 3.1 в начале 90-х.

Как мы уже знаем, для того, что открыть аудиоустройство вывода необходимо на вход функции waveOutOpen внести его идентификатор и информацию о формате, имеющую структуру WAVEFORMAT или WAVEFORMATEX.

И тут я столкнулся с такой проблемой, что WAVEFORMAT в целом не совместим с этой APIшкой. Даже если запускать программу с виндой помладше, мы все равно получим ошибку WAVERR_BADFORMAT.

Более того, в официальной документации Win32 Programmer’s Reference 1994 года присутствует только упоминание структуры WAVEFORMAT, когда как описание WAVEFORMATEX находится в заголовке mmsystem.h.

В общем, только с WAVEFORMATEX удалось заставить винду взаимодействовать с звуковой подсистемой.

А поскольку аудиодорожка составляет почти весь файл как есть и без промежутков, легче поделить её на кадры.

Для воспроизведения WAV-файла выделяется буфер размером в 32 кадра. Один кадр содержит 1024 сэмпла, размер сэмпла зависит от разрядности и количества аудиоканалов. Таким образом, получаем размер одного кадра в байтах:

8 бит, моно = 1024 * 1 * 1 = 1024 байта = 1 кБ 16 бит, моно = 1024 * 2 * 1 = 2048 байт = 2 кБ 16 бит, стерео = 1024 * 2 * 2 = 4096 байт = 4 кБ

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

Системная функция Sleep() такой точности не обладает. Мало того, что даже простая проверка флагов для WAVEHDR не спасает, так еще и на коллбек предстоит посмотреть поближе - а вдруг состояние готовности не совсем означает готовность залить следующий кадр перед выводом. Посмотрим.

Не обошлось и без нюанса, связанный с отображением имени аудиоустройства.

Строку с этим именем обязательно копируем в другой строковый указатель, чтобы случайно не повредить данные, а то SetConsoleCursorPosition очень любит стирать данные от прошлых Win32шных функций.

Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru Теперь же мой самодельный аудиодвижок научился выводить звук | Сетка — социальная сеть от hh.ru