Предисловие
Как известно, выход Windows Vista ознаменовался смертью звуковой подсистемы DirectSound и появление новой подсистемы Windows Audio Session Application Programming Interface (WASAPI). Я уже писал об этом неоднократно — в статье Организация качественного вывода звука и Как вернуть качественный звук в Windows 7.
Лично для меня подобный поворот событий оказался полной неожиданностью. Как я уже писал, в итоге Windows практически полностью потеряла доступ к аппаратным возможностям звуковых карт, а побитовый вывод аудио во многом усложнился. Конечно, надо отметить универсальность, простоту и удобство новой подсистемы — обратная совместимость со старыми приложениями, использующими Wave Out, DS), поддержка любой частоты дискретизации вплоть до 192 кГц, регулировка громкости для каждого приложения. Но, хотя прогресс IT и движется в направлении упрощения, «проще» — далеко не всегда значит «лучше». Скажем, изначально совершенно неизвестно было, каким образом работает ресемплинг WASAPI. Кроме того, в 16-битном режиме микшер вносил какие-то непонятные шумы, сокращающие динамический диапазон на десяток децибел.
Но, не всё так плохо. В WASAPI оказалось заложено много интересных возможностей, позволяющих выполнять тонкую настройку вывода, в том числе качества ресемплирования, латентности и проч. Благо, сейчас разработчики ПО всерьез взялись за реализацию этих возможностей.
Оборудование и ПО
Microsoft Windows 7 Ultimate SP1 x64
PlayPcmWin x64 4.0.62
RightMark Audio Analyzer 6.3.0
Adobe Audition CS6
Sony Sound Forge 10.0c
PlayPcmWin
Итак, недавно я разместил на сайте аудиофильский плеер PlayPcmWin, который как раз и предназначен для вывода через WASAPI, и, как следствие, наиболее полно реализует все возможности этого API. Так что начнем знакомство с системой с помощью этого плеера.
Программа имеет две версии — 32- и 64-битную. 64-битная версия позволяет снизить нагрузку на процессор, а также использовать больше оперативной памяти. Мы, как вы уже поняли, будем использовать PlayPcmWin x64.
Давайте запустим программу и рассмотрим элементы её главного окна.
Программа имеет простой и удобный интерфейс. Слева располагается плейлист с поддержкой drag'n'drop, ниже — элементы управления плейлистом и воспроизведением. Справа мы видим базовые настройки, выбор звукового устройства, а также информационные элементы — лог и кнопку получения списка поддерживаемых устройством форматов.
Для начала расскажу о настройках (WASAPI Settings). Настройка Operation mode отвечает за выбор режима воспроизведения — обычный (shared) или монопольный (exclusive). Второй режим доступен только если в настройках звукового устройства Windows включено разрешение его использования. В случае обычного режима, в котором работает большинство программ, написанных для Windows Vista и более новых ОС, Windows Audio Service может использовать все свои обработчики, изображенные на блок-схеме слева:
API — Application Programming InterfaceAPO — Audio Processing Object
CPT — Cross Process Transport
KST — Kernel Streaming Transport
Этот режим имеет некоторые возможности настройки, но об этом позже. Что касается режима монопольного — в нем отключаются все эти обработчики и звук поступает непосредственно на Kernel Streaming Transport. Так как у данного транспорта только один входной и один выходной поток (смешивание потоков с разных приложений происходит в Mixer APO), подключение непосредственно к KST ведет к блокированию всех остальных звуков.
Настройка Data feed mode отвечает за режим передачи данных, а точнее режим работы программного буфера. Режим Event driven является технически более совершенным, чем Timer driven (иногда называется Push), обладает пониженной нагрузкой на процессор и, как следствие, щелчки (и прочие артефакты) в этом режиме менее вероятны. Однако, есть устройства отказывающиеся работать в Event driven mode, тогда необходимо использовать режим Timer. Стоит отметить, что оба режима позволяют получить побитовое воспроизведение, и к качеству звучания это отношения не имеет.
Параметр латентность позволяет установить размер выходного буфера WASAPI. Это также не имеет отношения к качеству воспроизведения, и влияет лишь на отклик (скорость реакции) на изменения параметров воспроизведения. Однако, слишком низкий размер буфера неминуемо приведет к щелчкам при воспроизведении.
Далее есть очень интересная функция List supported formats. По нажатию на кнопку в поле лога появляется текстовая таблица следующего вида:
wasapi.Init() 00000000
wasapi.DoDeviceEnumeration(Play) 00000000
DwmEnableMMCSS(True) result=00000000
DwmEnableMMCSS(True) result=00000000
wasapi.InspectDevice()
DeviceFriendlyName=Динамики (Creative SB X-Fi)
DeviceIdString={0.0.0.00000000}.{7d0f79be-d721-4695-8ac8-6882f309abd7}
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
|| 44kHz i16V16|| 48kHz i16V16|| 88kHz i16V16|| 96kHz i16V16||176kHz i16V16||192kHz i16V16||352kHz i16V16||384kHz i16V16||
|| OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || NA 88890008 || NA 88890008 ||
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
|| 44kHz i24V24|| 48kHz i24V24|| 88kHz i24V24|| 96kHz i24V24||176kHz i24V24||192kHz i24V24||352kHz i24V24||384kHz i24V24||
|| NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 ||
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
|| 44kHz i32V24|| 48kHz i32V24|| 88kHz i32V24|| 96kHz i32V24||176kHz i32V24||192kHz i32V24||352kHz i32V24||384kHz i32V24||
|| OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || NA 88890008 || NA 88890008 ||
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
|| 44kHz i32V32|| 48kHz i32V32|| 88kHz i32V32|| 96kHz i32V32||176kHz i32V32||192kHz i32V32||352kHz i32V32||384kHz i32V32||
|| OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || OK 00000000 || NA 88890008 || NA 88890008 ||
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
|| 44kHz f32V32|| 48kHz f32V32|| 88kHz f32V32|| 96kHz f32V32||176kHz f32V32||192kHz f32V32||352kHz f32V32||384kHz f32V32||
|| NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 || NA 88890008 ||
++-------------++-------------++-------------++-------------++-------------++-------------++-------------++-------------++
Это информация о форматах аудио данных, которые поддерживает драйвер звуковой карты, т.е. фактически это форматы, которые могут поступать на Kernel Streaming Transport. Как видно из таблицы, устройство поддерживает стандартные семплрейты от 44.1 до 192 кГц. Что касается разрядности, условные обозначения здесь следующие: ixxVyy означает «xx бит с фиксированной точкой (integer), из них yy битов значащие». Т.е. i16V16 — обычный 16-битный формат с фиксированной точкой, f32V32 — 32-битный с плавающей точкой. i32V24 означает, что к 24-битным данным добавили 8 пустых битов и получили 32-битные. Этот прием используется в случае, когда карта не поддерживает на вход 24-битные данные, как например наша карта X-Fi.
Таким образом карта поддерживает стандартные форматы с фиксированной точкой, кроме 24-битного.
Расширенные настройки
По нажатию кнопки Detailed settings мы попадаем в расширенные настройки программы.
Первая группа настроек относится к монопольному режиму. Здесь можно выбрать формат данных, в котором будет выводиться звук. Здесь следует либо установить параметр в режим автовыбора, либо выбрать поддерживаемый режим с наибольшей разрядностью (см. таблицу). Также здесь можно включить дизеринг (по видимому, с нойз шейпингом), который будет выполняться при понижении разрядности (например, если источник 24-битный, а вывод — 16-битный). Кстати, давайте посмотрим на качество дизеринга.
NS on
NS off
Очень странно — никакого дизеринга, а уж тем более нойз шейпинга здесь не видно. Программа лишь добавляет какой-то странный дополнительный шум. Вероятно, это баг — я уже сообщил об этой странности разработчику.
Добавлено: по словам разработчика, обработка всё же выполняется и называется это формовкой шума первого порядка (first order noise shaping). Т.е. дополнительный шум в запись не вводится, а уже имеющийся шум квантования с помощью специального алгоритма, включающего обратную связь, вытесняется в область высоких частот. Разработчик также утверждает, что в качестве дизера могут запросто выступать естественные шумы микрофона, присутствующие на большинстве записей. Т.е. такой алгоритм даёт преимущественно лучшие результаты на живых, не синтетических записях. Добавлено: в весрии 4.0.63 была добавлена возможность использовать комбинации dither и noise shaping.Далее у нас следуют настройки общего режима WASAPI. Здесь мы можем управлять качеством ресемплера (resampler MFT или Audio resampler DSP), входящего в Windows Audio Service. Как написано в документации Microsoft, если программа не выполняет управление качество ресемплера, устанавливается значение по умолчанию — 30. Давайте сравним качество ресемплинга 44.1->96 кГц с качеством 1, 30 и 60 (максимум).
Q=1
Q=30
Q=60
На слух минимальное качество имеет значительные искажения, режимы качества 30 и 60 на слух практически одинаково приемлемы. Кстати, интересно, что управление качеством ресемплинга было введено только в Windows 7.
Здесь же имеется настройка автоматического масштабирования сигнала по амплитуде до 98% от максимума, что предотвращает вмешательство лимитера Windows (иначе он будет компрессировать сигнал).
Что касается режима Shared — с особенностями его работы вы можете ознакомиться в обзоре Windows Media Player.
И последняя группа настроек, которая нас интересует — Playback thread settings, т.е. настройки потока воспроизведения. Здесь мы сталкиваемся с новшеством под названием MMCSS (Multimedia Class Scheduler Service). Эта служба занимается распределением процессорных ресурсов между процессами, отвечающими за выполнение задачи реального времени — записи, воспроизведения (рендеринга). Включив данную функцию (DwmEnableMMCSS(True) и установив тип задачи в Pro Audio, мы тем самым установим для проигрывания максимальный приоритет доступа к ЦП, что позволит еще больше уменьшить латентность (размер буфера). Таким образом, установка режима Pro Audio уменьшает вероятность опустошения буфера (что и является причиной щелчков), однако этот режим менее эффективен с точки зрения эффективности энергопотребления.
В общем, это все, настройки, касающиеся качества воспроизведения. Следует также добавить, что перед воспроизведением плейлиста программа выполняет декодирование и необходимую обработку (например, дизеринг или масштабирование амплитуды), помещая результат в оперативной памяти компьютера в выбранном формате (для монопольного режима используется режим выбранный в настройках, для общего - исходный формат). Вот пример лога после запуска и включения трека:
wasapi.Init() 00000000
wasapi.DoDeviceEnumeration(Play) 00000000
wasapi.ChooseDevice(Динамики (Creative SB X-Fi)) 00000000
wasapi.Setup(PCM 44.1kHz Sint32V24 2ch ProAudio Exclusive EventDriven latency=3ms zeroFlush=500ms timePeriod=0.5ms) 00000000
Endpoint buffer size = 132 frames.
Read playgroup 0 completed. Elapsed time: 1632ms
wasapi.StartPlayback(0) 00000000
Продолжительность трека — около 6 минут. После запуска программа потребляла 70 Мб ОЗУ, после включения трека — 212 Мб.
Как вы можете видеть на скриншоте. мне удалось осуществить вывод аудио в формате i32V24 с задержкой всего 3 мс. При этом звуковые артефакты не наблюдались
Что самое интересное — в режиме Shared программа выполняет ресемплирование средствами алгоритма resampler MFT, а затем получает поток обратно, помещая уже ресемпилрованное аудио в ОЗУ (т.е. ресемплинг выполняется не на лету). Вот лог:
wasapi.Init() 00000000
wasapi.DoDeviceEnumeration(Play) 00000000
wasapi.ChooseDevice(Динамики (Creative SB X-Fi)) 00000000
wasapi.Setup(PCM 44.1kHz Sint16 2ch ProAudio Shared EventDriven latency=3ms zeroFlush=500ms timePeriod=0.5ms) 00000000
Endpoint buffer size = 2880 frames.
Resampling...
Read playgroup 0 completed. Elapsed time: 6677ms
wasapi.StartPlayback(0) 00000000
После начала произведения программа потребляла около 340 Мб ОЗУ.
PlayPcmWin поддерживает форматы WAV, AIFF, FLAC, а также имеет поддержку CUEsheet.
Выводы
Данная программа, вне всяких сомнений, представляет интерес только для энтузиастов. PlayPcmWin наглядно демонстрирует нам все возможности Windows Audio Service, которые оказались довольно широкими. Несмотря на отсутствие полного доступа к аппаратным ресурсам (как в DirectSound), WASAPI имеет широкие возможности программной обработки звука, а также позволяет организовать вывод звука с низкой задержкой.
Информация от спонсора
SEGA-gamer.RU: портал для фанатов SEGA. Здесь Вы можете скачать игры и эмулятор Сега. Эмулятор Gens — один из лучших на сегодня эмуляторов Sega Mega Drive. Gens позволяет запускать 16- и 32-битные образы картриджей для SEGA.