Концепция синхронного вывода звука через WASAPI Exclusive
Благодаря тестам, проведенным некоторыми откликнувшимися добрыми людьми, написал некоторое текущее резюме:
Концепция синхронного вывода звука через WASAPI Exclusive:
Система вывода звука, появившаяся начиная с Windows Vista под названием WASAPI, хороша тем, что в эксклюзивном режиме использования (режим, когда звук может выводить только одно приложение) позволяет следующее:
1) Выдает наиболее качественный звук, т.к. отсутствую какие-либо программные микшеры.
2) Позволяет задать самую маленькую задержку между моментом записи программой звука в буфер и вывода звука на динамики.
3) И, что наиболее важно и интересно для меня в плане написании эмулятора с синхронным обновлением звука и видео - это возможность получать точную информацию о текущей позиции в буфере проигрывания. Исключением являются звуковухи, не умеющие проецировать свой аудиобуфер в ОЗУ. Например, USB-звуковые карты (и то под вопросом, все ли?).
Вывод звука в эксклюзивном режиме бывает двух типов:
1. Event:
В данном режиме для уменьшения задержи вывода звука, рекомендуется выбирать наименьший размер звукового буфера. Эксперименты показывают, что размер наименьшего буфера для Win7-10 почти всегда одинаков, и равен 3ms.
Далее, система выделяет 2 буфера заданного размера, и при окончании проигрывания каждого из них, выдает системное событие (Event), среагировав на которое, программа пользователя заполняет освободившийся буфер и может заснуть до следующего события. В данном режиме проигрывание буферов идет в стиле Пинг-Понг, т.е. то один буфер, то другой, по очереди.
Преимуществом данного режима является то, что программе пользователя нет необходимости следить за позицией проигрывания в буфере, тратя на это ресурсы.
Минусом данного режима является то, что невозможно заполнять буфер частями, с произвольным опережением позиции воспроизведения. Таким образом, минимальная задержка вывода звука не может быть меньше размера буфера (хотя 3мс - это весьма малая задержка, и более, чем достаточна почти для любых целей).
2. Push:
В данном режиме буфер воспроизведения как бы один (почему как бы, поясню позже), и может иметь размеры вплоть до 0.5сек. Воспроизведение буфера идет всегда по кругу, при этом пользовательской программе дается возможность точного (в большинстве случаев) отслеживания текущей позиции воспроизведения. В любой момент времени, программа может спросить у системы - милая, а сколько тебе осталось проиграть из того фрагмента, что я тебе засунул в буфер? А система и говорит - мне осталось проиграть 30%. Тогда программа говорит, окей, тогда дай мне тот кусок буфера, что у тебя уже проигран. Система говорит - да легко, бери. И дает указатель на уже не нужный ей фрагмент буфера. Программа может записать в него следующий звуковой фрагмент, и сказать системе - я записала тебе новых 70% данных. Система говорит, окей, буду играть теперь свои 30% плюс твои 70%. И все идет по кругу.
Судя по всему (как показывают эксперименты), система сама следит за закольцовкой буфера в режиме записи в него данных. Скорее всего это выглядит так: у системы два последовательно расположенных в памяти буфера, и когда программа записывает данные в начало второго буфера, система автоматически переносит их в начало первого буфера. Таким образом, о закольцовывании буфера программе пользователя думать не надо.
Ну, и самое главное, благодаря точному отслеживанию позиции воспроизведения, можно добиться хорошей синхронизации видео и аудио в эмуляторе. О важности этого можно прочитать в начале ветки.
Замечания:
1) Звуковухи Audigy-2 и Aydigy-5 были замечены в том, что в режиме Event выдавали размер буфера в 8 раз превышающий запрошенный. С чем это связано, не известно.
2) Внешние USB звуковухи имеют грубую дискретность определения текущей позиции в буфере, таким образом, построить на основе них точных синхронный эмулятор вряд ли представляется возможным. Однако, не исключено, что существуют и точные внешние звуковухи.
3) Все звуковухи поддерживают режим 16бит, 48kГц, что является требованием самой Виндовс.
Большинство звуковух поддерживают форматы 44.1кГц, 96кГц. Некоторые поддерживают и 192кГц. Так же, некоторые звуковухи поддерживают режим 24бита. Звуковух, поддерживающих 32 бита пока встречено не было.
4) Звуковые карты умеют выделять как буферы точно запрошенного размера (например, при запрошенных 24000 байтах, их и выделяют, что в шестнадцатиричном равно 0x5DC0), так и выровненные к большему числу, кратному 0x1000 (а может и 0x2000) в шестнадцатиричном. Т.е. при запрошенных 24000 байтах, выделяется 24576 (0x6000).
5) Адрес буфера аудиокарточки выделяют как произвольный, так и выровненный на 64Кб.