Программирование звука в DirectSound
- Основные черты и понятия DirectSound
- Назначение и структура
- Смешивание сигналов
- Объемный звук
- Использование аппаратных ускорителей
- Конфигурация звукоизлучателей
- Звуковые буферы
- Размещение звуковых буферов
- Первичный и вторичные буферы
- Статические и потоковые буферы
- Порядок создания вторичных буферов
- Управление режимами вторичных буферов
- Позиции в буфере
- Уровни взаимодействия
- Потеря буферов
- Эмуляция
- Задержки звука
- Идентификация устройств
- Уведомление о наступлении событий
- Наборы свойств
- Именование интерфейсных функций
- Совместимость
- Общая схема взаимодействия программы и DirectSound
- Программирование в DirectSound
- Средства разработки, включаемые файлы и библиотеки
- Структуры, используемые при работе с подсистемой
- DSCAPS - параметры устройства воспроизведения
- DSBCAPS - параметры звукового буфера
- DSBUFFERDESC - описатель создаваемого буфера
- DSCCAPS - параметры устройства захвата
- DSCBCAPS - параметры буфера захвата
- DSCBUFFERDESC - описатель создаваемого буфера захвата
- DSBPOSITIONNOTIFY - описатель позиции для уведомления
- Уведомление приложения о наступлении событий
- Набор интерфейсных функций подсистемы
- Внеинтерфейсные функции высшего уровня
- Интерфейс IUnknown
- QueryInterface - запрос интерфейса из набора
- Интерфейс IDirectSound
- Initialize - инициализация устройства
- SetCooperativeLevel - установка уровня взаимодействия
- CreateSoundBuffer - создание звукового буфера
- DuplicateSoundBuffer - создание копии объекта буфера
- GetCaps - запрос параметров и состояния устройства
- GetSpeakerConfig - запрос конфигурации звукоизлучателей
- SetSpeakerConfig - установка конфигурации звукоизлучателей
- Compact - уплотнение внутренней памяти адаптера
- Интерфейс IDirectSoundBuffer
- Initialize - инициализация объекта буфера
- Restore - восстановление памяти потерянного буфера
- GetCaps - запрос параметров буфера
- GetFormat - запрос текущего формата буфера
- SetFormat - установка формата буфера
- Lock - запрос обновления данных в буфере
- Unlock - завершение обновления данных в буфере
- Play - запуск звучания буфера
- Stop - прекращение проигрывания буфера
- GetStatus - запрос состояния буфера
- GetCurrentPosition - запрос текущих позиций буфера
- SetCurrentPosition - установка позиции воспроизведения буфера
- GetFrequency - запрос частоты дискретизации
- SetFrequency - установка частоты дискретизации
- GetPan - запрос текущего положения источника на панораме
- SetPan - установка текущего положения источника на панораме
- GetVolume - запрос уровня громкости источника
- SetVolume - установка уровня громкости источника
- Интерфейс IDirectSoundCapture
- Интерфейс IDirectSoundCaptureBuffer
- Initialize - инициализация объекта буфера
- GetCaps - запрос параметров буфера
- GetFormat - запрос формата буфера
- GetCurrentPosition - запрос текущих позиций буфера
- GetStatus - запрос состояния буфера
- Lock - открывание процедуры извлечения данных
- Unlock - завершение процедуры извлечения данных
- Start - запуск захвата в буфер
- Stop - остановка захвата в буфер
- Интерфейс IDirectSoundNotify
- Интерфейс IKsPropertySet
- Недостатки DirectSound
- Типичные применения DirectSound
- Оптимизация вывода звука в DirectSound
DirectSound - сравнительно новый программный интерфейс, входящий в семейство интерфейсов DirectX (DirectDraw, Direct3D, DirectInput и т.п.). Первым продуктом данного семейства является интерфейс Direct Draw, созданный почти одновременно с Windows 95 и предназначенный для оптимизации работы игровых приложений с видеоадаптером. Затем к нему добавились интерфейсы Direct3D, DirectInput, а впоследствии для многих классических интерфейсов с оконечными устройствами были введены Direct-версии.
Название DirectX трактуется буквально - . Классические системные интерфейсы с видео-, звуковыми и игровыми адаптерами относятся к Windows первых версий, когда внутренняя организация большинства адаптеров была достаточно разношерстной, многие решения находились в стадии отработки, а приложениям требовалось в первую очередь отображать прямоугольные окна, текст и графики, проигрывать длительные непрерывные звукозаписи и т.п. С массовым переходом производителей игр на платформу Windows и развитием видеотехнологий выяснилось, что большинство классических интерфейсов слишком абстрактны, поэтому при работе с конкретным устройством возникают заметные накладные расходы, ощутимо снижающие быстродействие; при частой и хаотичной перерисовке элементов экрана, выводе коротких одновременных звуков выполняется множество лишних операций. Семейство DirectX было разработано именно для того, чтобы приблизить аппаратуру к приложению, предоставив эффективный интерфейс.
Ценой эффективности явилось снижение универсальности интерфейсов, более явная привязка их к определенным схемам и протоколам взаимодействия. Для полной поддержки DirectX необходима установка специального расширенного DirectX-драйвера; традиционные драйверы устройств, как правило, для этого не годятся. В первые несколько лет существования DirectX выпуск DirectX-драйверов часто отставал от выпуска устройств; сейчас этот разрыв практически отсутствует, хотя далеко не все драйверы поддерживают полный набор заявленных функций. В случае появления новых технологий вывода изображения и звука может оказаться, что они не укладываются в схему DirectX, и тогда потребуется серьезная переработка как интерфейсов, так и использующих их приложений.
Интерфейсы семейства DirectX состоят из общесистемной части - подсистем DirectX, с которыми общаются приложения, и набора драйверов с поддержкой DirectX - обычных драйверов устройств, в которые добавлена поддержка новых объектов и функций. Центральной частью любой подсистемы DirectX является HAL (Hardware Abstraction Layer - уровень отвлечения от аппаратуры) - промежуточный интерфейс, который скрывает частные, непринципиальные особенности используемых аппаратных средств, но сохраняет полный контроль над основными, ключевыми возможностями аппаратуры. HAL реализуется на уровне драйвера устройства.
Поддержка DirectX включена в стандартную поставку начиная с Windows 98 и NT 5. В системах Windows 95, OSR2 и NT 4 поддержка DirectX не предусмотрена, однако Microsoft выпускает отдельные расширения для Windows 9x и NT, установка которых восполняет в системе отсутствующие компоненты - собственно подсистемы и распространенные драйверы.
Поддержка интерфейсов DirectX есть в большинстве систем программирования C++, Pascal и Basic, выпущенных после 1995 года. Семейство имеет целый ряд версий; в настоящее время используется версия 7. Если в среде программирования поддерживаются только более старые версии, можно заменить включаемые файлы и библиотеки на более новые, содержащие обновленные версии подсистем, взяв их из новой версии DirectX SDK.
Описания подсистем также имеются в поддерживающих их средах программирования. Более новые версии описаний распространяются Microsoft в составе DirectX SDK. Microsoft поддерживает в Internet справочную систему MSDN Online, где интерфейсы DirectX описаны в разделе http://msdn.microsoft.com/library/psdk/directx/dxstart_1x2d.htm, а сам DirectSound - в http://msdn.microsoft.com/library/psdk/directx/dsover_9dno.htm.
Основные черты и понятия DirectSound
Назначение и структура
Подсистема DirectSound обеспечивает приложениям практически непосредственный доступ к аппаратуре звукового адаптера. Этот факт вовсе не означает, что приложению приходится вникать в детали программирования того или иного адаптера - это остается прерогативой HAL. Вместо этого приложению предоставляется модель современного звукового адаптера, предельно приближенная к реальности, с минимальным уровнем абстракции. При таком подходе общение приложения с адаптером сопровождается минимальными накладными расходами, и в то же время избавляет приложение от излишних подробностей программирования аппаратуры.
Подсистема DirectSound построена по объектно-ориентированному принципу в соответствии с моделью COM (Component Object Model - модель объектов-компонентов, или составных объектов) и состоит из набора интерфейсов. Каждый интерфейс отвечает за объект определенного типа - устройство, буфер, службу уведомления и т.п. По сути, интерфейс представляет собой обычный набор управляющих функций, или методов, организованных в класс объектно-ориентированного языка.
DirectSound не поддерживает звуковые форматы, отличные от PCM. Назначение DirectSound - исключительно эффективный вывод звука, а операции по преобразованию форматов остаются в ведении приложений, которые могут использовать для этого подсистему сжатия звука (ACM).
Смешивание сигналов
Одно из наиболее неудобных ограничений MME/Wave - невозможность проигрывания нескольких звуков на одном устройстве одновременно без их программного смешивания самим приложением. DirectSound снимает это ограничение, позволяя приложению просто задавать несколько источников звука, которые будут проиграны одновременно. Количество таких источников ограничено только доступной памятью и быстродействием аппаратуры.
Объемный звук
Источники звука, работающие в базовой модели DirectSound, могут быть только моно- стереофоническими. Работа расширенной базовой модели, DirectSound3D, основана на другой концепции, позволяющей размещать монофонические источники звука в пространстве. Для каждого источника, а также для самого слушателя, задаются координаты в пространстве, ориентация, направление и скорость перемещения. DirectSound3D обрабатывает все источники и создает для слушателя объемную и реалистичную звуковую картину с учетом интерференции, затухания, направленности, эффекта Доплера и т.п.
В этой статье рассматривается только базовая модель DirectSound. Расширение DirectSound3D будет описано в следующих выпусках.
Использование аппаратных ускорителей
При наличии у используемого звукового адаптера средств аппаратного ускорения (hardware acceleration) - смешивания нескольких источников звука, обсчета трехмерной модели, создания звуковых эффектов и т.п. - DirectSound всю возможную работу старается переложить на аппаратуру адаптера. Использование аппаратного ускорения остается прозрачным для приложения - DirectSound использует возможности аппаратуры там, где это можно, а в остальных случаях выполняет нужную работу на программном уровне. Тем не менее приложениям, использующим большое количество одновременно звучащих источников или сложную трехмерную картину, имеет смысл упрощать свою модель при отсутствии средств аппаратного ускорения, иначе накладные расходы могут существенно снизить общую производительность системы.
Для реализации на аппаратном уровне смешивания и звуковых эффектов необязательно нужен современный адаптер с шиной PCI. Многие комбинированные адаптеры с шиной ISA - семейство Sound Blaster AWE, Turtle Beach Maui/Tropez/Pinnacle, Guillemot MaxiSound - имеют встроенные таблично-волновые синтезаторы с расширяемой оперативной памятью. Если синтезатор свободен и у него достаточно свободной памяти, DirectSound может загрузить туда некоторое количество источников звука и проигрывать их средствами синтезатора.
Конфигурация звукоизлучателей
Для создания реалистичной звуковой картины DirectSound нуждается в информации о расположении звукоизлучателей - громкоговорителей или наушников - относительно слушателя. Для достижения максимального эффекта звукоизлучатели должны быть установлены и настроены правильно, а приложение должно указать используемую конфигурацию подсистеме DireсtSound.
Звуковые буферы
Большинство существующих звуковых адаптеров использует для обмена звуком с центральным процессором звуковые буферы, представляющие собой участок памяти, в который заносятся звуковые данные. Обычно буфер является кольцевым, то есть указатель текущей позиции при достижении конца буфера автоматически перебрасывается на его начало, совершая внутри буфера круговое движение. Адаптер и его драйвер работают параллельно с разными частями буфера, стараясь следовать друг за другом и не создавать конфликтов; если их работа достаточно согласованна - получается непрерывное движение сколь угодно длительного звукового потока.
В отличие от концепции связанной цепочки программных буферов, принятой в MME, DirectSound предоставляет приложению почти прямой доступ к аппаратным буферам адаптера. В этой концепции просто смещены акценты: вывод коротких и повторяющихся звуков значительно упрощается, а вывод длительных непрерывных звучаний несколько усложняется относительно модели MME.
Размещение звуковых буферов
Различные адаптеры используют буферы разного типа. Классические адаптеры типа Sound Blaster, Windows Sound System и совместимые с ними используют буфер в основной памяти компьютера с доступом через DMA. Адаптеры архитектуры Hurricane (Turtle Beach Tahiti, Fiji и совместимые) используют буфер в собственной (on-board) памяти, который доступен в виде в диапазоне адресов внешних устройств. Существуют также адаптеры со встроенным буфером, доступ к которому осуществляется через порты ввода-вывода; обычно так работают таблично-волновые синтезаторы.
В зависимости от размещения и способа управления различают аппаратные (hardware) и программные (software) буферы. Аппаратным называют буфер, к которому адаптер имеет прямой доступ; такой буфер располагается либо в памяти самого адаптера, либо в основной памяти с обращением через DMA или Bus Mastering. Программные буферы всегда располагаются в основной памяти и управляются центральным процессором, адаптер к таким буферам прямого доступа не имеет.
В документации по DirectSound аппаратными называют только те буферы, которые
находятся в памяти адаптера, и нередко путают термин
Первичный и вторичные буферы
Если в архитектуре адаптера один из аппаратных буферов является основным, его называют первичным (primary). Остальные буферы, занимающие подчиненное положение, называются вторичными (secondary). Обычно звуки из вторичных буферов смешиваются воедино в первичном буфере, откуда и поступают на ЦАП адаптера.
Для адаптеров типа SB/WSS, работающих только с одним буфером, он и является первичным; вторичные буферы могут быть только программными и управляются самой подсистемой DirectSound. И наоборот, для современных многоканальных адаптеров PCI, имеющих несколько равноправных каналов вывода звука, первичный буфер недоступен, зато некоторое количество вторичных может быть аппаратными, и управление звуками в них осуществляет непосредственно сам адаптер.
Чаще всего приложению не требуется использовать первичный буфер. В типовой схеме взаимодействия для каждого источника звука создается свой вторичный буфер (в DirectSound часто отождествляются понятия и ). Впоследствии приложение в нужные моменты включает и выключает звучание источников, меняет текущую позицию в звуке, параметры звучания и т.п. Вторичные буферы могут иметь произвольные размеры, которые задаются приложением при их создании. Даже если смешивание выполняет DirectSound - оно осуществляется на уровне ядра (VxD или системно).
В исключительных случаях возможен прямой доступ к первичному буферу. При этом запрещается использование вторичных буферов - то есть приложение теряет возможность описывать независимые источники звука. Зато наличие доступа к первичному буферу гарантирует, что все изменения в звуковых данных будут услышаны максимально быстро (единицы миллисекунд). Однако первичный буфер имеет фиксированный размер, выбираемый драйвером DirectSound, и размер этот достаточно мал (несколько десятков миллисекунд звучания). Для того чтобы успевать вписывать звук в первичный буфер, приложение должно иметь высокий уровень приоритета. Но даже в этом случае Windows не гарантирует нужной скорости, не являясь системой реального времени.
Статические и потоковые буферы
Вторичный буфер может быть статическим (static) и потоковым (streaming). Статические буферы предназначены для постоянных звуков, цифровое представление которых не меняется либо меняется достаточно редко. Потоковые буферы ориентированы на часто изменяемые звуки, как правило - на представление длительного звукового потока, который по частям через буфер.
Статические и потоковые буферы различаются только тем, что подсистема старается в первую очередь делать аппаратными статические буферы, загружая их в память адаптера. Таким образом, постоянные и короткие звуки оказываются в распоряжении адаптера, и достаточно лишь дать команду, чтобы они включились в общее звучание.
При желании приложение может явно указывать при создании буфера тип памяти для его размещения.
Порядок создания вторичных буферов
DirectSound оптимизирует использование вторичных буферов в порядке их создания приложением; источники звука, созданные в первую очередь, имеют приоритет в использовании аппаратных средств. Буферы, созданные первыми, подсистема старается по возможности загружать в память адаптера, предоставлять им каналы DMA, ресурсы Bus Mastering и т.п.; при исчерпании аппаратных ресурсов DirectSound переходит на самостоятельную, программную обработку оставшихся буферов.
Управление режимами вторичных буферов
Поскольку каждый вторичный буфер описывает независимый источник звука, подсистема предоставляет средства управления режимами звучания источника. Для базовых источников DirectSound доступно управление громкостью, панорамой и частотой дискретизации; для источников DirectSound3D еще и пространственными координатами, направленностью и скоростью движения.
Набор необходимых для источника методов управления задается при создании буфера и позволяет подсистеме оптимально связывать буферы с аппаратными ресурсами. Впоследствии доступны только заказанные методы управления; для изменения набора необходимо уничтожить буфер и создать его заново.
Позиции в буфере
DirectSound использует для адресации в звуковых буферах понятие текущих позиций, или курсоров. Различают позицию записи/воспроизведения, отслеживающую проигрывание звука из буфера в адаптер или запись звука из адаптера в буфер, и позицию доступа, отслеживающую чтение/запись (обмен данными) между приложением и буфером. В первичной англоязычной документации первая позиция называется Play/Capture Position, а вторая - Read/Write Position, поэтому отсутствуют коллизии между значениями термина . Для обозначения ввода звука извне я также буду пользоваться термином (capture).
Позиция воспроизведения (play) следует за позицией записи (write) в буфер, а позиция чтения (read) - за позицией захвата (capture). Достижение позицией воспроизведения позиции записи означает полное проигрывание буфера воспроизведения, при этом начинают воспроизводиться данные, которые приложение не успело перезаписать. Достижение позицией захвата позиции чтения означает переполнение буфера захвата, и последующие данные накладываются на , которые приложение не успело извлечь из буфера.
Уровни взаимодействия
DirectSound вводит четыре уровня взаимодействия (cooperation levels) приложений между собой и звуковым адаптером. Когда несколько приложений одновременно используют один и тот же адаптер, соотношение уровней взаимодействия определяет их приоритетность в использовании аппаратуры и создании звучания.
- Обычный (normal) уровень фиксирует формат первичного буфера адаптера - 22 050 Гц, стерео, 8-разрядные отсчеты. Форматы вторичных буферов преобразуются в этот формат, и при переключении приложений подсистеме нет необходимости изменять формат первичного буфера. На этом уровне достигается наибольшая универсальность и, кроме того, эффективность, однако качество звука в таком формате весьма посредственно и не допускается уплотнение (оптимизация) внутренней памяти адаптера.
- Приоритетный (priority) уровень позволяет приложению устанавливать формат первичного буфера и уплотнять внутреннюю память адаптера - то есть предоставляет приоритетный доступ к аппаратным ресурсам, когда окно приложения становится активным (foreground). Если происходит переключение между приложениями этого уровня, установившими различные форматы первичного буфера, - подсистема вынуждена переключать форматы, для чего необходим перезапуск адаптера, нередко порождающий щелчки и тому подобные помехи.
- Исключительный (exclusive) уровень подобен приоритетному, но на время активности окна приложения ему предоставляется исключительный доступ к адаптеру, и звучание источников всех остальных приложений заглушается (но не останавливается).
- Уровень доступа к первичному буферу (write-primary) разрешает приложению прямую запись в первичный буфер адаптера. Этот уровень доступен только для устройств, имеющих специализированный DirectSound-драйвер. На этом уровне приложение может работать только с первичным буфером, активизация вторичных буферов запрещена.
Потеря буферов
Когда приложение, запросившее высший (write-primary) уровень взаимодействия, становится активным, подсистеме приходится передавать ему управление первичным буфером, теряя при этом собственный контроль над ним. И наоборот, когда активным становится приложение с менее высоким уровнем, подсистема возвращает себе контроль над буфером, но теперь его теряет приложение. В этой ситуации, называемой потерей буферов (buffer lose), буфер прекращает звучание и его содержимое теряется.
Когда приложение высшего уровня становится активным, звучание всех вторичных буферов приложений более низких уровней останавливается, а сами буферы помечаются как потерянные. Это происходит потому, что подсистема не может правильно отслеживать текущие позиции во вторичных буферах, не имея доступа к первичному буферу адаптера. И наоборот, когда приложение высшего уровня становится неактивным, его первичный буфер также помечается как потерянный.
Приложения получают сообщение о потере буферов при попытках обращения к ним в виде кода ошибки DSERR_BUFFERLOST. Все приложения должны корректно обрабатывать эту ситуацию и выполнять восстановление потерянных буферов.
Эмуляция
Подсистема DirectSound может обходиться без поддержки со стороны драйвера. В этом случае нужная функциональность эмулируется через MME - традиционную звуковую подсистему Windows. Однако такая эмуляция крайне неэффективна, поскольку при этом подсистеме DirectSound приходится эмулировать первичный буфер в обычной памяти, смешивать в нем звуки из вторичных буферов, затем представлять его в виде цепочки буферов, передаваемых драйверу MME, который, в свою очередь, разбивает их на фрагменты и переносит в звуковой буфер адаптера. При этом каждое обращение к драйверу MME сопровождается переключением в 16-разрядный режим и обратно.
Отметим, что без наличия специализированного DirectSound-драйвера невозможно получить высший (write-primary) уровень взаимодействия с адаптером.
Тем не менее поддержка захвата (capture) звука в DirectSound реализована только методом эмуляции. Для драйверов DirectSound VxD определены лишь функции поддержки воспроизведения - дальше в унификации этого интерфейса Microsoft почему-то не пошла. Операции записи и воспроизведения с точки зрения адаптера почти идентичны и различаются в основном направлением движения данных. Однако прямой доступ к буферу адаптера в режиме записи позволил бы значительно повысить эффективность обработки входного сигнала в реальном времени. Поддержка записи звука определена только для драйверов WDM.
Задержки звука
Подсистема MME из-за переключений между 32- и 16-разрядными режимами и неоптимальной с точки зрения адаптера структуры буферов часто дает существенную задержку (latency) между подачей звукового блока драйверу и появлением звука на выходе, равно как и в обратном направлении (при записи). DirectSound, за счет более оптимального управления адаптером, вносит задержки на уровне около 20 мс. Однако при эмуляции, когда работа идет через подсистему MME, задержки могут возрасти до 100-150 мс.
Идентификация устройств
В отличие от подсистем MME, идентификация устройств в DirectSound следует правилам COM и использует GUID (Globally Unique IDentifier - идентификатор, уникальный в мировом масштабе). Любой объект COM имеет свой идентификатор, по которому приложения могут обращаться к нему. Идентификаторы доступных устройств приложение получает в процессе перебора (enumeration) устройств заданного класса.
Уведомление о наступлении событий
Событием в подсистеме DirectSound считается достижение одной из заданных позиций в звуковом буфере. Для запроса уведомления о наступлении таких событий приложение может использовать специальный интерфейс IDirectSoundNotify, создавая соответствующие ему следящие объекты. При достижении указанных позиций следящий объект активизирует (set) заданные объекты события (event objects), которые могут быть опрошены приложением непосредственно, либо может быть создана отдельная задача (thread), ожидающая активизации одного или нескольких объектов событий.
Наборы свойств
DirectSound вводит понятие набора свойств (property set) - параметров, описывающих виды обработки звука. При помощи набора свойств можно описать параметры зала, голоса исполнителя, манеры пения, звучания инструментов и т.п. При наличии необходимых средств обработки одну и ту же звуковую картину можно представлять в разных ракурсах, активизируя нужные наборы свойств.
В данное время эти виды обработки почти не поддерживаются; наборы свойств введены в основном на будущее.
Именование интерфейсных функций
Различные интерфейсы имеют наборы функций (методов) с разными именами, поэтому в ссылках я буду приводить только имена методов, не снабжая их именем интерфейса. В прототипах имена всех методов приводятся полностью, с указанием интерфейса.
Поскольку ряд интерфейсов имеет схожую структуру (IDirectSound/IDirectSoundCapture, IDirectSoundBuffer/IDirectSound3DBuffer), многие методы являются общими для нескольких интерфейсов сразу. В таких случаях я буду упоминать имя интерфейса, только если в использовании одного и того же метода в разных интерфейсах существует принципиальная разница.
Совместимость
Интерфейсы DirecSound доступны для платформ Windows 98 или 2000 и выше. В Windows 95 интерфейсы становятся доступными после установки пакета DirectX. В Windows NT 4/SP3 доступен только базовый уровень функциональности - интерфейсы IDirectSound и IDirectSoundBuffer.
Общая схема взаимодействия программы и DirectSound
Приложение начинает работу с DirectSound, создавая объект устройства с интерфейсом IDirectSound - для воспроизведения звука или IDirectSoundCapture - для захвата (записи) звука. Объект устройства воспроизведения создается функцией DirectSoundCreate, объект устройства захвата - DirectSoundCaptureCreate.
При создании объекта устройства указывается идентификатор устройства, которое будет через него программироваться. Приложение может либо запросить доступ к устройству по умолчанию, либо получить перечень идентификаторов доступных устройств функцией перебора - DirectSoundEnumerate или DirectSoundCaptureEnumerate.
Функции перебора требуют указания локальной перебирающей функции приложения (callback), которая будет вызываться для каждого доступного устройства. Перебирающая функция может либо самостоятельно выбрать подходящее устройство, либо сформировать полный список устройств, из которого пользователь сделает выбор по своему усмотрению.
Созданный объект устройства может быть опрошен методом GetCaps, возвращающим его характеристики и возможности. Таким образом может быть, например, найдено минимально и оптимально подходящее для целей приложения устройство из всех имеющихся в системе.
Перед началом работы с устройством необходимо установить уровень взаимодействия методом SetCooperativeLevel.
Работа со звуком начинается с создания объектов звуковых буферов. Если приложение работает на обычном уровне взаимодействия, первичный буфер не создается. На остальных уровнях необходимо создать первичный буфер методом CreateSoundBuffer и задать его формат методом SetFormat. На обычном уровне взаимодействия формат первичного буфера фиксирован - 22 050 Гц, стерео, восемь разрядов.
Объекты вторичных звуковых буферов также создаются при помощи метода CreateSoundBuffer - по одному для каждого источника звука; в этом же вызове задаются и форматы буферов. Для коротких звуков длительностью до нескольких секунд удобнее создавать статические буферы, целиком вмещающие цифровое представление звуков. Для длительных звуков рекомендуется создавать небольшие (порядка десятков-сотен килобайт) потоковые буферы, через которые будут непрерывно фрагменты длительного звучания.
Создав вторичный буфер, приложение должно заполнить его звуковыми данными. Процедуру занесения данных в буфер открывает метод Lock, возвращающий указатели доступных участков буфера. Эти участки заполняются данными, после чего вызывается метод Unlock, завершающий процедуру обновления данных.
При желании приложение может разделить один и тот же экземпляр звучания между несколькими объектами буферов, создавая объекты-копии методом DuplicateSoundBuffer. Впоследствии, изменяя параметры звучания, можно получать различные звуки на основе одной и той же оцифровки, не расходуя дополнительную память.
Для запуска воспроизведения буфера вызывается метод Play, для остановки - Stop. Чтобы определить, какой фрагмент звучит в данный момент, используется метод GetCurrentPosition, для запуска звучания с определенного места - SetCurrentPosition.
При необходимости приложение может изменить параметры звучания в буфере: частоту дискретизации (SetFrequency), громкость (SetVolume), положение на панораме (SetPan). Для пространственных источников возможно изменение координат, ориентации, скорости движения и т.п.
Для корректной работы приложение должно отслеживать ситуацию потери буферов. Получив от методов Lock или Play сообщение о потере буфера, необходимо приостановить генерацию звука и периодически выполнять метод Restore до тех пор, пока он не даст положительного результата. После этого буфер следует вновь заполнить звуковыми данными.
Захват (запись) звука производится с помощью объектов устройств IDirectSoundCapture. Здесь нет разделения на первичный и вторичные буферы, поэтому методом CreateCaptureBuffer создается единственный буфер захвата, которому этим же методом приписывается нужный формат. Затем методом Start запускается захват звука, который может быть остановлен методом Stop. Для извлечения звуковых данных из буфера служат методы Lock и Unlock. Процесс захвата во многом симметричен процессу воспроизведения, поэтому в описании интерфейсов захвата упомянуты лишь их отличия от основных интерфейсов.
При желании приложение может воспользоваться интерфейсом уведомления IDirectSoundNotify, запрашивая его у объектов тех буферов, для которых требуются уведомления, и заказывая установку заданных объектов программных событий (event objects) по достижении определенных позиций в буфере.
Завершая работу, приложение уничтожает методом Release объекты буферов, а затем - объекты устройств.
Программирование в DirectSound
Средства разработки, включаемые файлы и библиотеки
Описывается программирование на языке C++ в среде Microsoft Visual C++. DirectSound поддерживает программирование и из обычного C, однако использование C++ позволяет более естественно оформлять работу с интерфейсами и не ведет к какому бы то ни было увеличению объектного кода по сравнению с C, поскольку модель DirectSound изначально ориентирована на объекты и методы обращения к ним из C++.
Полный комплект DirectX 7.0a SDK занимает 128 Мбайт, однако наиболее важные его части доступны отдельно. Набор документации включаемых заголовочных файлов и библиотек занимает 1,3 Мбайт и доступен по ссылке http://download.microsoft.com/download/win98SE/DXSDK/7.0/W9X/EN-US/dx7libhdr.exe.
Вместе с демонстрационной программой к статье прилагаются файлы dsound.h и dsound.lib из комплекта DirectX SDK 7.0a. Тем не менее одних этих файлов недостаточно для построения примера; среда разработки должна поддерживать хотя бы одну из версий DirectX.
Структуры, используемые при работе с подсистемой
Все структуры имеют поле dwSize, в которое при инициализации структуры необходимо занести ее размер в байтах. Размер используется для определения версии интерфейса. Это единственное поле, которое требует обязательной инициализации во всех структурах; остальные поля заполняются, только если они являются входными.
DSCAPS - параметры устройства воспроизведения
Данная структура описывает возможности и параметры устройства воспроизведения. Для удобства определен тип LPCDSCAPS - константный указатель на тип DSCAPS.
DWORD dwSize; DWORD dwFlags; DWORD dwMinSecondarySampleRate; DWORD dwMaxSecondarySampleRate; DWORD dwPrimaryBuffers; DWORD dwMaxHwMixingAllBuffers; DWORD dwMaxHwMixingStaticBuffers; DWORD dwMaxHwMixingStreamingBuffers; DWORD dwFreeHwMixingAllBuffers; DWORD dwFreeHwMixingStaticBuffers; DWORD dwFreeHwMixingStreamingBuffers; DWORD dwMaxHw3DAllBuffers; DWORD dwMaxHw3DStaticBuffers; DWORD dwMaxHw3DStreamingBuffers; DWORD dwFreeHw3DAllBuffers; DWORD dwFreeHw3DStaticBuffers; DWORD dwFreeHw3DStreamingBuffers; DWORD dwTotalHwMemBytes; DWORD dwFreeHwMemBytes; DWORD dwMaxContigFreeHwMemBytes; DWORD dwUnlockTransferRateHwBuffers; DWORD dwPlayCpuOverheadSwBuffers; DWORD dwReserved1; DWORD dwReserved2;
- dwSize - размер структуры в байтах;
- dwFlags - флаги характеристик устройства. Имена флагов имеют префикс DSCAPS_:
CONTINUOUSRATE |
Устройство поддерживает любые значения частоты дискретизации - от минимальной до максимальной с точностью примерно до 10 Гц. Отсутствие этого флага означает поддержку только стандартных частот - 8000, 11 025, 22 050 и т.д. |
---|---|
PRIMARY16BIT |
В первичном буфере поддерживаются 16-разрядные форматы |
PRIMARY8BIT |
В первичном буфере поддерживаются 8-разрядные форматы |
PRIMARYMONO |
В первичном буфере поддерживаются монофонические форматы |
PRIMARYSTEREO |
В первичном буфере поддерживаются стереофонические форматы |
SECONDARY16BIT |
Аппаратный микшер поддерживает вторичные буферы в 16-разрядных форматах |
SECONDARY8BIT |
Аппаратный микшер поддерживает вторичные буферы в 8-разрядных форматах |
SECONDARYMONO |
Аппаратный микшер поддерживает вторичные буферы в монофонических форматах |
SECONDARYSTEREO |
Аппаратный микшер поддерживает вторичные буферы в стереофонических форматах |
EMULDRIVER |
Устройство не имеет специализированного драйвера, и DirectSound эмулирует интерфейсы посредством стандартной подсистемы MME/Wave |
CERTIFIED |
Драйвер устройства проверен и сертифицирован Microsoft |
- dwMinSecondarySampleRate, dwMaxSecondarySampleRate - минимальная и максимальная частота дискретизации, поддерживаемая для аппаратных вторичных буферов;
- dwPrimaryBuffers - количество поддерживаемых первичных буферов. В текущей модели всегда равно единице;
- dwMaxHwMixingAllBuffers - максимальное общее количество поддерживаемых буферов с аппаратным смешиванием. Может быть меньше суммы числа статических и потоковых буферов из-за различия способов их организации в аппаратуре;
- dwMaxHwMixingStaticBuffers - максимальное количество статических звуковых буферов с аппаратным смешиванием;
- dwMaxHwMixingStreamingBuffers - максимальное количество потоковых звуковых буферов с аппаратным смешиванием;
- dwFreeHwMixingAllBuffers, dwFreeHwMixingStaticBuffers, dwFreeHwMixingStreamingBuffers - количество свободных буферов с аппаратным смешиванием - всех, статических и потоковых;
- dwMaxHw3DAllBuffers, dwMaxHw3DStaticBuffers, dwMaxHw3DStreamingBuffers - максимальное количество аппаратных буферов для источников объемного звука - всех, статических и потоковых;
- dwFreeHw3DAllBuffers, dwFreeHw3DStaticBuffers, dwFreeHw3DStreamingBuffers - количество свободных аппаратных буферов для источников объемного звука - всех, статических и потоковых.
- dwTotalHwMemBytes - общий объем внутренней памяти адаптера, доступной для размещения статических буферов;
- dwFreeHwMemBytes - объем свободной внутренней памяти адаптера;
- dwMaxContigFreeHwMemBytes - объем наибольшего непрерывного участка внутренней памяти адаптера;
- dwUnlockTransferRateHwBuffers - скорость пересылки данных из основной памяти в память адаптера (Кбайт/с). Пересылка выполняется при вызове метода Unlock, время отработки метода может быть определено из значения этого поля и объема занесенных в буфер звуковых данных;
- dwPlayCpuOverheadSwBuffers - приблизительная доля времени центрального процессора (в %), необходимая для смешивания звука из буферов, расположенных в основной памяти;
- dwReserved1, dwReserved2 - служебные поля.
DSBCAPS - параметры звукового буфера
Структура описывает возможности и параметры существующего звукового буфера. Для удобства определен тип LPCDSBCAPS - константный указатель на тип DSBCAPS.
DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; DWORD dwUnlockTransferRate; DWORD dwPlayCpuOverhead;
- dwSize - размер структуры в байтах;
- dwFlags - флаги возможностей, параметров и режимов буфера. Имена констант флагов имеют префикс DSBCAPS_:/
PRIMARYBUFFER |
Буфер является первичным. Если флаг не установлен - буфер является вторичным |
---|---|
STATIC |
Буфер является статическим |
LOCHARDWARE |
Буфер размещается в памяти адаптера |
LOCSOFTWARE |
Буфер размещается в основной памяти |
LOCDEFER |
Размещение буфера в определенном типе памяти отложено до момента его активизации |
CTRL3D |
Допускается управление пространственным звучанием (координаты, скорость, ориентация и т.п.). Флаг относится к расширению DirectSound3D |
CTRLFREQUENCY |
Допускается управление частотой дискретизации |
CTRLPAN |
Допускается управление панорамой (стереобалансом) |
CTRLVOLUME |
Допускается управление громкостью |
CTRLPOSITIONNOTIFY |
Допускается заказ уведомлений о достижении заданных позиций буфера. Перед проигрыванием такого буфера необходимо заказать уведомление посредством интерфейса IDirectSoundNotify |
GETCURRENTPOSITION2 |
Метод GetCurrentPosition возвращает более правильное положение позиции воспроизведения для эмулируемых устройств. В первой версии DirectX, за счет задержек при эмуляции метод возвращал позицию, значительно опережающую реальное звучание. В последующих версиях была введена компенсация, вычисление которой включается при задании этого флага |
GLOBALFOCUS |
Источник звука, представленный буфером, является глобальным и будет звучать независимо от того, является приложение текущим (foreground) или нет. Однако, если текущим становится приложение с исключительным или более высоким уровнем взаимодействия, источники звука всегда заглушаются |
STICKYFOCUS |
Источник звука, представленный буфером, будет звучать при переключении на приложения, не использующие DirectSound. Обычные источники, не объявленные глобальными, заглушаются, если текущим становится другое приложение. Этим флагом рекомендуется снабжать источники фонового звука - например, музыки. Однако, если текущим становится приложение, использующее DirectSound, источники с этим флагом также заглушаются |
MUTE3DATMAXDISTANCE |
Звучание источника должно быть остановлено при достижении максимального расстояния от слушателя, где звук перестает быть слышимым. В этот момент DirectSound прекращает снижать громкость источника и останавливает его, во избежание лишних расходов. При уменьшении расстояния звучание будет запущено автоматически. Этот флаг относится только к буферам, описывающим пространственные источники |
Необходимо иметь в виду, что даже если звук источников, помеченных как звучащие в фоне (когда приложение не является текущим), будет слышен при переключении на другое приложение, то этот звук может приводиться к другому формату. Например, если одно приложение использует стереофонический формат и фоновые источники и происходит переключение на приложение, устанавливающее монофонический формат, звук от фоновых источников также станет монофоническим. Если текущее приложение устанавливает менее качественный формат - звук от более качественных фоновых источников может приобретать заметные искажения вследствие понижения разрядности и/или частоты дискретизации;
- dwBufferBytes - размер буфера в байтах;
- dwUnlockTransferRate - скорость загрузки данных в буфер (килобайт в секунду). Для буферов, расположенных в основной памяти, скорость обычно значительно выше, чем для расположенных в памяти адаптера. Это значение позволяет оценить время выполнения метода Unlock, осуществляющего пересылку данных в буфер;
- dwPlayCpuOverhead - доля процессорного времени (в %), необходимая для добавления (смешивания) звучания данного буфера в общий звук. Для буферов с аппаратным смешиванием это значение равно нулю, для программно смешиваемых оно зависит от скорости процессора, формата этого и первичного буферов.
DSBUFFERDESC - описатель создаваемого буфера
Структура описывает конфигурацию и свойства создаваемого звукового буфера. Для удобства определен тип LPDSBUFFERDESC - указатель на тип DSBUFFERDESC.
DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; DWORD dwReserved; LPWAVEFORMATEX lpwfxFormat; GUID guid3DAlgorithm;
- dwSize - размер структуры в байтах;
- dwFlags - флаги параметров и режимов работы буфера. Определены в описании слова флагов структуры DSBCAPS;
- dwBufferBytes - размер буфера в байтах. При создании первичного буфера должно быть задано нулевое значение, так как размеры первичных буферов определяются подсистемой. Фактический размер созданного первичного буфера можно узнать посредством его метода GetCaps. Для вторичных буферов размер должен лежать в диапазоне от DSBSIZE_MIN до DSBSIZE_MAX;
- dwReserved - служебное поле;
- lpwfxFormat - адрес структуры WAVEFORMATEX, описывающей формат буфера. Для первичного буфера поле должно иметь нулевое значение - формат первичного буфера всегда устанавливается методом SetFormat;
- guid3DAlgorithm - алгоритм моделирования объемного звука системой из двух звукоизлучателей (громкоговорителей или наушников). Относится только к буферам пространственных источников, используемых в DirectSound3D. Для обычных моно- и стереоисточников значение поля игнорируется.
Флаги LOCHARDWARE и LOCSOFTWARE являются взаимоисключающими. Они запрашивают размещение буфера в памяти адаптера или компьютера, однако не гарантируют, что это будет соблюдено. О фактическом размещении буфера можно узнать при помощи его метода GetCaps.
Описанный формат структуры используется начиная с DirectX 7.0. До этого использовалась структура, не содержавшая поля guid3DAlgorithm; для совместимости старый формат сохранен под именем DSBUFFERDESC1. Подсистема определяет версию структуры, используя значение поля dwSize, и корректно обрабатывает наличие или отсутствие дополнительного поля.
DSCCAPS - параметры устройства захвата
Описывает возможности и параметры устройства записи (захвата). Для удобства определен тип LPCDSCCAPS - константный указатель на тип DSCCAPS.
DWORD dwSize; DWORD dwFlags; DWORD dwFormats; DWORD dwChannels;
- dwSize - размер структуры в байтах;
- dwFlags - флаги параметров устройства. Имена констант имеют префикс DSCCAPS_:
EMULDRIVER |
Для устройства нет специализированного драйвера DirectSound, и интерфейсы эмулируются подсистемой через стандартные функции MME |
---|---|
CERTIFIED |
Драйвер является сертифицированным драйвером WDM |
- dwFormats - стандартные форматы, поддерживаемые устройством. Флаги форматов эквивалентны используемым в структуре MME WAVEINCAPS. Имена констант флагов имеют вид WAVE_FORMAT_fcnn, где f - символ частоты дискретизации (1 - 11025 Гц, 2 - 22050 Гц, 4 - 44100 Гц), c - символ количества каналов (M - моно, S - стерео), а nn - разрядность отсчета (08 или 16). Таким образом, всего определено 12 стандартных форматов;
- dwChannels - количество каналов устройства (1 - моно, 2 - стерео, и т.п.).
DSCBCAPS - параметры буфера захвата
Описывает параметры существующего буфера захвата. Для удобства определен тип LPCDSCBCAPS - константный указатель на тип DSCBCAPS.
DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; DWORD dwReserved;
- dwSize - размер структуры в байтах;
- dwFlags - флаги параметров. Пока определен только один флаг - DSCBCAPS_WAVEMAPPED, разрешающий использование Wave Mapper для форматов, не поддерживаемых устройством непосредственно и для которых в работу неявно может быть включена подсистема сжатия ACM;
- dwBufferBytes - размер буфера в байтах;
- dwReserved - служебное поле.
DSCBUFFERDESC - описатель создаваемого буфера захвата
Описывает конфигурацию и свойства создаваемого буфера захвата. Для удобства определен тип LPDSCBUFFERDESC - указатель на тип DSCBUFFERDESC.
DWORD dwSize; DWORD dwFlags; DWORD dwBufferBytes; DWORD dwReserved; LPWAVEFORMATEX lpwfxFormat.
Как видно, структура аналогична DSBUFFERDESC, за исключением поля guid3DAlgorithm. В версиях DirectX до 7.0, где в структуре DSBUFFERDESC этого поля не было, форматы описателей создаваемых буферов для устройств воспроизведения и записи были тождественны.
Различия касаются также поля dwFlags, содержащего управляющие флаги. В описываемой структуре оно может содержать только флаг DSCBCAPS_WAVEMAPPED.
DSBPOSITIONNOTIFY - описатель позиции для уведомления
Описывает позицию звукового буфера, при достижении которой выполняется уведомление. Определен также вспомогательный тип LPDSBPOSITIONNOTIFY - указатель структуры.
DWORD dwOffset; HANDLE hEventNotify;
- dwOffset - смещение от начала буфера, при достижении которого должно быть выполнено уведомление. Специальное значение DSBPN_OFFSETSTOP запрашивает уведомление в момент остановки звучания - либо методом Stop, либо при достижении конца буфера;
- hEventNotify - ключ объекта события (event object handle), который устанавливается (set) для выполнения уведомления.
Если для буфера разрешено досрочное прекращение звучания при нехватке аппаратных ресурсов и звучание буфера прекращается по этой причине, уведомление не выполняется.
Уведомление приложения о наступлении событий
В подсистеме DirectSound существует только одно асинхронное событие - это достижение заданной позиции внутри звукового буфера. Как частный случай событие может возникать при остановке звучания буфера - методом Stop, или при естественном достижении конца буфера.
Подсистема использует для уведомления только объекты программных событий (event objects). Это не так удобно, как в подсистеме MME, предоставляющей несколько видов уведомлений, однако вполне в духе многозадачной модели Win32, когда для управления буферами и перезагрузки их содержимого создается отдельная задача (thread). Эта задача не занимается ничем посторонним, ожидая установки одного из заданных объектов событий, после которой выполняет обновление отработанной части буфера.
Для одного буфера может быть указано сколько угодно позиций, при достижении которых происходит уведомление. Таким образом удобно, например, разделить буфер на две или более частей, и каждое уведомление будет означать, что отработана очередная часть буфера. С помощью такого механизма достигается эффективное и в то же время плавное продвижение длительного звукового потока через буфер небольшого размера, как это и делается в звуковых драйверах низкого уровня.
Набор интерфейсных функций подсистемы
Описание функций распределено по разделам, каждый из которых, в свою очередь, описывает соответствующий интерфейс DirectSound. Несколько общих функций высшего уровня, не принадлежащих интерфейсам, вынесено в начало описания.
Перечень базовых интерфейсов DirectSound
IUnknown |
Базовый интерфейс для всех объектов COM |
---|---|
IDirectSound |
Интерфейс устройства воспроизведения |
IDirectSoundBuffer |
Интерфейс буфера воспроизведения |
IDirectSoundCapture |
Интерфейс устройства захвата |
IDirectSoundCaptureBuffer |
Интерфейс буфера захвата |
IDirectSoundNotification |
Интерфейс уведомления |
IKsPropertySet |
Интерфейс дополнительных наборов свойств |
Перечень внеинтерфейсных функций высшего уровня
DirectSoundEnumerate |
Перебор устройств воспроизведения |
---|---|
DirectSoundCreate |
Создание объекта устройства воспроизведения |
DirectSoundCaptureEnumerate |
Перебор устройств захвата |
DirectSoundCaptureCreate |
Создание объекта устройства захвата |
Значения, возвращаемые функциями и методами
Все функции и методы интерфейсов возвращают результат типа HRESULT, эквивалентный типу LONG. Значение DS_OK равное нулю означает успешное выполнение функции, любое другое значение указывает на ошибку. Константы для кодов ошибок имеют префиксы DSERR_:
ACCESSDENIED |
Доступ запрещен |
---|---|
ALLOCATED |
Запрошенный ресурс занят |
ALREADYINITIALIZED |
Объект уже инициализирован |
BADFORMAT |
Запрошенный формат не поддерживается |
BUFFERLOST |
Буфер потерян и должен быть восстановлен |
CONTROLUNAVAIL |
Запрошенный вид управления буфером недоступен - не поддерживается или не был заказан при создании буфера |
GENERIC |
Неустановленная ошибка внутри подсистемы |
HWUNAVAIL |
Аппаратура адаптера недоступна |
INVALIDCALL |
Метод недопустим в текущем состоянии объекта |
INVALIDPARAM |
Функции передан неверный параметр |
NOAGGREGATION |
Объект не поддерживает дополнительных интерфейсов |
NODRIVER |
Нет доступного драйвера |
NOINTERFACE |
Запрошенный интерфейс COM недоступен |
OTHERAPPHASPRIO |
Другое приложение имеет более высокий уровень взаимодействия |
OUTOFMEMORY |
Недостаточно памяти |
PRIOLEVELNEEDED |
Недостаточно высок уровень взаимодействия приложения |
UNINITIALIZED |
Объект не инициализирован |
UNSUPPORTED |
Операция не поддерживается |
Внеинтерфейсные функции высшего уровня
Enumerate - перебор устройств воспроизведения или захвата
HRESULT DirectSoundEnumerate ( LPDSENUMCALLBACK EnumCallback, LPVOID Context ); HRESULT DirectSoundCaptureEnumerate ( DSENUMCALLBACK EnumCallback, VOID *Context );
- EnumCallback - указатель перебирающей функции, которая будет вызываться для каждого обнаруженного устройства;
- Context - произвольное 32-разрядное значение, которое будет передаваться перебирающей функции при каждом вызове. Например, это может быть описатель параметров искомого устройства, указатель области памяти для найденного идентификатора и т.п.
EnumCallback - перебирающая функция
BOOL CALLBACK EnumCallback ( LPGUID GUID, LPCSTR Description, LPCSTR Module, VOID *Context );
- GUID - указатель идентификатора очередного найденного устройства;
- Description - строка названия устройства;
- Module - строка имени модуля драйвера устройства;
- Context - 32-разрядное значение, заданное в функции Enumerate.
Функция вызывается для каждого найденного устройства заданного класса. Если возвращается значение TRUE - перебор продолжается, если FALSE - прекращается.
Create - создание объекта устройства воспроизведения или захвата
HRESULT WINAPI DirectSoundCreate ( LPCGUID GUID, LPDIRECTSOUND *Dev, LPUNKNOWN Outer ); HRESULT WINAPI DirectSoundCaptureCreate ( LPCGUID GUID, LPDIRECTSOUNDCAPTURE *Dev, LPUNKNOWN Outer );
- GUID - указатель идентификатора устройства либо нулевое значение для использования стандартного устройства;
- Dev - указатель переменной, в которую будет занесен указатель созданного объекта;
- Outer - указатель наружного интерфейса COM. Не используется, должен иметь нулевое значение.
После успешного создания устройства воспроизведения, до начала проигрывания звуковых источников приложение должно установить уровень взаимодействия методом SetCooperativeLevel.
Интерфейс IUnknown
Является базовым для всех интерфейсов COM и содержит средства фиксации объекта, его освобождения и запроса нужного интерфейса из набора (агрегата).
QueryInterface - запрос интерфейса из набора
HRESULT IUnknown::QueryInterface ( REFIID IID, LPVOID *Obj );
- IID - идентификатор (GUID) требуемого интерфейса;
- Obj - указатель переменной, в которую будет занесен указатель объекта, имеющего требуемый интерфейс.
Если объект, для которого интерфейс IUnknown является базовым, имеет указанный интерфейс, то в заданную переменную заносится указатель объекта, через который доступен запрашиваемый интерфейс.
Обычно в качестве переменной выступает указатель объекта того типа, который имеет запрашиваемый интерфейс в своем составе. Например, при получении интерфейса IDirectSound3DBuffer из объекта с указателем Buf типа IDirectSoundBuffer вызывается метод
Buf->QueryInterface (IID_IDirectSound3DBuffer, (LPVOID *)&Buf3D),
где Buf3D - указатель объекта типа IDirectSound3DBuffer. Указатели Buf и Buf3D обычно ссылаются на один и тот же объект, однако рассчитывать на это не стоит.
При успешном завершении функция возвращает код S_OK (нуль). Возможными кодами ошибки могут быть E_NOINTERFACE (исходный объект не имеет требуемого интерфейса) и E_POINTER (передан недопустимый указатель переменной).
Счетчик ссылок полученного объекта увеличивается на единицу. При завершении работы с полученным интерфейсом необходимо освободить объект методом Release.
AddRef - фиксация объекта
ULONG IUnknown::AddRef ();
Увеличивает счетчик ссылок объекта на единицу. При создании объекта счетчик устанавливается в единицу, при получении нового интерфейса счетчик автоматически увеличивается на единицу.
При завершении работы с объектом должен быть вызван метод Release, уменьшающий счетчик ссылок на единицу. Когда количество ссылок становится нулевым, объект уничтожается.
Функция возвращает значение обновленного счетчика ссылок.
Release - освобождение объекта
ULONG IUnknown::Release ();
Уменьшает счетчик ссылок объекта на единицу. При обнулении счетчика объект уничтожается. Метод должен вызываться для всех объектов, полученных приложением, при завершении работы с ними.
Интерфейс IDirectSound
Обслуживает объекты устройств воспроизведения. Содержит следующие методы:
Initialize |
Инициализация устройства |
---|---|
SetCooperativeLevel |
Установка уровня взаимодействия с аппаратурой |
CreateSoundBuffer |
Создание звукового буфера |
DuplicateSoundBuffer |
Создание копии объекта буфера |
GetCaps |
Запрос возможностей и параметров устройства |
Compact |
Уплотнение внутренней памяти звукового адаптера |
GetSpeakerConfig |
Запрос конфигурации звукоизлучателей |
SetSpeakerConfig |
Установка конфигурации звукоизлучателей |
Initialize - инициализация устройства
HRESULT IDirectSound::Initialize ( LPCGUID GUID );
- GUID - идентификатор устройства либо нулевое значение для выбора стандартного устройства.
Метод используется для объектов, созданных не специальной функциями Create, а стандартным для COM методом CoCreateInstance. Функции Create возвращают инициализированный объект, в то время как CoCreateInstance - объект-заготовку, который не связан с конкретным устройством.
SetCooperativeLevel - установка уровня взаимодействия
HRESULT IDirectSound::SetCooperativeLevel ( HWND Win, DWORD Level );
- Win - ключ окна (window handle), по положению которого определяется состояние приложения. Когда окно становится текущим (foreground), приложение также считается текущим, и наоборот. Если приложение использует DirectDraw, то в методах установки уровня DirectDraw и DirectSound должно использоваться одно и то же окно.
- Level - запрашиваемый уровень взаимодействия. Имена констант кодов уровней имеют префикс DSSCL_:;
NORMAL |
Обычный уровень. Формат первичного буфера фиксирован. Когда приложение является текущим, звучат только его собственные источники, а также источники других приложений, помеченные флагом DSBCAPS_GLOBALFOCUS |
---|---|
PRIORITY |
Приоритетный уровень. Подобен обычному, но допускаются смена формата первичного буфера и уплотнение памяти адаптера. Когда приложение становится текущим, подсистема переключает формат выводимого через адаптер звука |
EXCLUSIVE |
Исключительный уровень. Сверх приоритетного, запрещается звучание всех источников остальных приложений, когда приложение становится активным |
WRITEPRIMARY |
Уровень доступа к первичному буферу. Разрешается прямой доступ к первичному буферу, однако запрещается использование вторичных буферов. Установка уровня допускается только для устройств, имеющих драйвер DirectSound (флаг DSCAPS_EMULDRIVER в свойствах устройства не установлен) |
CreateSoundBuffer - создание звукового буфера
HRESULT IDirectSound::CreateSoundBuffer ( LPCDSBUFFERDESC BufferDesc, LPDIRECTSOUNDBUFFER *Buffer, IUnknown *Outer );
- BufferDesc - указатель заполненного описателя создаваемого буфера (структура DSBUFFERDESC);
- Buffer - указатель переменной, в которую будет занесен указатель созданного объекта буфера;
- Outer - указатель объекта интерфейса IUnknown. Не используется, должен иметь нулевое значение.
Метод создает звуковой - первичный или вторичный буфер, в зависимости от состояния флага DSBCAPS_PRIMARYBUFFER. При создании буфера должны быть указаны способы управления (флаги DSBCAPS_CTRLxxx), которые будут использоваться при проигрывании буфера.
Если заданы флаги DSBCAPS_LOCHARDWARE, DSBCAPS_LOCSOFTWARE, подсистема сразу же пытается разместить буфер в памяти определенного типа. Если задан флаг DSBCAPS_LOCDEFER, размещение буфера откладывается до запуска его звучания.
DuplicateSoundBuffer - создание копии объекта буфера
HRESULT IDirectSound::DuplicateSoundBuffer ( LPDIRECTSOUNDBUFFER Original, LPLPDIRECTSOUNDBUFFER Duplicate );
- Original - указатель копируемого объекта;
- Duplicate - указатель переменной, в которую заносится указатель объекта-копии.
Метод служит для создания копии объекта, описывающего звуковой буфер, и используется для создания источников, разделяющих между собой один звуковой фрагмент. Оба объекта ссылаются на один и тот же участок памяти, и изначально их параметры полностью совпадают. Впоследствии приложение может изменять параметры каждого из объектов, что дает соответственное изменение звучания. Например, если это звук автомобиля, то методом копирования объектов можно создать звучания нескольких одинаковых автомобилей, различающихся громкостью, высотой, положением в пространстве и т.п., не затрачивая дополнительную память для самой звуковой оцифровки.
GetCaps - запрос параметров и состояния устройства
HRESULT IDirectSound::GetCaps ( DSCAPS *Caps );
- Caps - указатель структуры DSCAPS, которая будет заполнена параметрами устройства. Перед обращением к методу должно быть установлено поле dwSize, определяющее версию интерфейса.
GetSpeakerConfig - запрос конфигурации звукоизлучателей
HRESULT IDirectSound::GetSpeakerConfig ( DWORD *Config );
- Config - адрес переменной, в которую будет занесен код текущей конфигурации звукоизлучателей для данного устройства. Имена констант значений кодов имеют префикс DSSPEAKER_:;
MONO |
Одиночный громкоговоритель |
---|---|
STEREO |
Стереофонические громкоговорители; (стандартно) |
HEADPHONE |
Наушники |
QUAD |
Квадрафонические громкоговорители |
SURROUND |
Громкоговорители, включенные по системе Surround |
5POINT1 |
Громкоговорители Surround с добавлением общего низкочастотного (subwoofer) |
В конфигурации STEREO добавляется код расположения громкоговорителей. Имена значений кодов имеют префикс DSSPEAKER_GEOMETRY_:
MIN |
Под углом в 5° |
---|---|
NARROW |
Под углом в 10° |
WIDE |
Под углом в 20° |
MAX |
Под углом в 180° |
Для выделения из двойного слова кодов конфигурации и расположения используются макросы DSSPEAKER_CONFIG и DSSPEAKER_GEOMETRY.
SetSpeakerConfig - установка конфигурации звукоизлучателей
HRESULT IDirectSound::SetSpeakerConfig ( DWORD Config );
- Config - набор флагов, описывающих конфигурацию.
Метод устанавливает новую конфигурацию звукоизлучателей, которая будет учитываться при создании результирующей звуковой картины.
Для объединения кодов конфигурации и расположения используется макрос DSSPEAKER_COMBINED (Config, Geometry).
Compact - уплотнение внутренней памяти адаптера
HRESULT IDirectSound::Compact ();
Метод выполняет уплотнение внутренней памяти адаптера, устраняя фрагментацию и собирая все неиспользуемые фрагменты в один непрерывный участок.
Для использования метода приложение должно иметь уровень взаимодействия не ниже приоритетного.
Интерфейс IDirectSoundBuffer
Обслуживает звуковые буферы устройства воспроизведения. Содержит следующие методы:
Initialize |
Инициализация объекта буфера |
---|---|
Restore |
Восстановление памяти потерянного буфера |
GetCaps |
Запрос параметров буфера |
GetFormat |
Запрос формата буфера |
SetFormat |
Установка формата буфера |
GetStatus |
Запрос состояния буфера |
GetCurrentPosition |
Запрос текущих позиций в буфере |
SetCurrentPosition |
Установка текущей позиции воспроизведения в буфере |
Lock |
Запрос обновления данных в буфере |
Unlock |
Завершение обновления данных в буфере |
Play |
Запуск воспроизведения буфера |
Stop |
Остановка воспроизведения буфера |
GetVolume |
Запрос текущей громкости звука |
SetVolume |
Установка текущей громкости звука |
GetPan |
Запрос текущей позиции на панораме |
SetPan |
Установка текущей позиции на панораме |
GetFrequency |
Запрос текущей частоты дискретизации |
SetFrequency |
Установка текущей частоты дискретизации |
Initialize - инициализация объекта буфера
HRESULT IDirectSoundBuffer::Initialize ( DIRECTSOUND *DevObj, LPCDSBUFFERDESC BufferDesc );
- DevObj - указатель объекта устройства DirectSound;
- BufferDesc - указатель описателя буфера (структура DSBUFFERDESC).
Метод инициализирует объект звукового буфера в соответствии с заданным описателем. При создании буфера методом IDirectSound::CreateSoundBuffer возвращается уже инициализированный объект буфера. Метод IDirectSoundBuffer::Initialize предназначен для унификации и будущих расширений интерфейса.
Restore - восстановление памяти потерянного буфера
HRESULT IDirectSoundBuffer::Restore ();
Метод восстанавливает память и параметры потерянного звукового буфера. Попытка восстановления буфера также может завершиться ошибкой DSERR_BUFFERLOST; это означает, что текущим в данный момент по-прежнему является приложение с более высоким уровнем взаимодействия. В этом случае необходимо дождаться, пока приложение само станет текущим либо конкурирующее приложение снизит свой уровень.
После успешного восстановления буфера его содержимое не определено, поэтому необходимо вновь заполнить буфер. Поскольку любая попытка заполнения или запуска буфера может закончиться ошибкой DSERR_BUFFERLOST, рекомендуется организовать эту работу в цикле, работающем до успешного заполнения и запуска буфера, и при неудачах - дожидающегося смены состояния или просто делающего небольшие паузы.
GetCaps - запрос параметров буфера
HRESULT IDirectSoundBuffer::GetCaps ( DSBCAPS *Caps );
- Caps - указатель описателя параметров буфера (структура DSBCAPS), который будет заполнен подсистемой. Поле dwSize должно быть установлено до обращения к методу.
Метод заполняет заданный описатель параметрами буфера, по которым можно судить о его размещении и возможностях использования. Поле флагов описывает реальные параметры размещения буфера, которые могут и не совпадать с запрошенными в описателе DSBUFFERDESC при создании буфера.
GetFormat - запрос текущего формата буфера
HRESULT IDirectSoundBuffer::GetFormat ( WAVEFORMATEX *Format, DWORD SizeAllocated, DWORD *SizeWritten );
- Format - указатель области памяти для описателя формата (структура WAVEFORMATEX), который будет заполнен параметрами формата буфера, или нуль;
- SizeAllocated - размер в байтах области памяти описателя;
- SizeWritten - указатель переменной, в которую будет занесен реальный размер заполненного описателя, или нуль, если размер не требуется.
Подсистема заполняет не более, чем SizeAllocated, байтов указанной области памяти. Если описатель не помещается в отведенную область, он обрезается.
Если указатель области имеет нулевое значение, в переменную по указателю SizeWritten заносится размер области памяти, необходимый для размещения полного описателя.
SetFormat - установка формата буфера
HRESULT IDirectSoundBuffer::SetFormat ( LPCWAVEFORMATEX Format );
- Format - указатель описателя формата (структура WAVEFORMATEX).
Метод устанавливает новый формат первичного звукового буфера. Для вторичных буферов задание формата возможно только при их создании; формат существующего объекта вторичного буфера изменить невозможно.
Право установки формата первичного буфера имеют только приложения с уровнем взаимодействия не ниже приоритетного. Подсистема поддерживает только форматы PCM.
На уровне доступа к первичному буферу перед сменой формата буфера необходимо остановить его работу методом Stop. На более низких уровнях, где нет прямого доступа приложения к буферу, подсистема выполняет остановку и перезапуск самостоятельно.
Если первичный буфер не поддерживает устанавливаемый формат, ошибки не возникает. В этом случае подсистема устанавливает наиболее близкий формат и прозрачно преобразует звуковые данные при их занесении в буфер. Определить реально установленный формат можно при помощи метода GetFormat.
Lock - запрос обновления данных в буфере
HRESULT IDirectSoundBuffer::Lock ( DWORD WriteCursor, DWORD WriteBytes, LPVOID *Ptr1, DWORD *Bytes1, LPVOID *Ptr2, DWORD *Bytes2, DWORD Flags );
- Cursor - смещение (относительно начала буфера) участка, к которому запрашивается прямой доступ;
- Bytes - размер участка в байтах;
- Ptr1, Ptr2 - указатели переменных, в которых будут возвращены указатели частей полученного участка памяти. Поскольку буферы фактически являются кольцевыми, полученный участок может пересекать границу буфера и на его начало. Если получен непрерывный участок, в переменной Ptr2 возвращается нулевое значение, иначе этот указатель всегда ссылается на начало буфера;
- Bytes1, Bytes2 - указатели переменных, в которых будут возвращены размеры частей полученного участка памяти. Если получен непрерывный участок, в переменной Bytes2 возвращается нулевое значение;
- Flags - флаги, уточняющие операцию. Имена констант флагов имеют префикс DSBLOCK_:
FROMWRITECURSOR |
Запрашивается участок буфера начиная с позиции (курсора) записи. В этом случае параметр Cursor игнорируется |
---|---|
ENTIREBUFFER |
Запрашивается доступ ко всему доступному для записи участку буфера. В этом случае параметр Bytes игнорируется |
При задании нулевых значений в параметрах Ptr1 и Bytes1 подсистема предоставляет доступ только к непрерывной части буфера, не выполняя через границу.
Метод открывает процедуру обновления данных в буфере. Не гарантируется, что возвращенные указатели будут ссылаться внутрь самого буфера и предоставленный участок памяти будет содержать какие-либо звуковые данные. При запросе обновления программного буфера метод действительно возвращает указатели на его участки, однако при работе с аппаратным буфером, размещенным в памяти адаптера, к которой нет прямого доступа со стороны процессора, подсистема вынуждена создавать временный буфер в основной памяти, указатели на который и возвращаются методом.
При успешном завершении метода приложению необходимо в кратчайший срок занести в предоставленные участки буфера нужные звуковые данные, после чего вызвать метод Unlock, который завершает процедуру обновления и, если данные были записаны во временный буфер, - пересылает их в память адаптера. Недостаточно быстрое заполнение буфера может привести к его опустошению и сбоям в звучании.
Unlock - завершение обновления данных в буфере
HRESULT IDirectSoundBuffer::Unlock ( VOID *Ptr1, DWORD Bytes1, VOID *Ptr2, DWORD Bytes2 );
- Ptr1, Ptr2 - указатели обновленных участков буфера, возвращенные ранее методом Lock;
- Bytes1, Bytes2 - количества байтов, реально записанных в обновленные участки.
Метод завершает процедуру обновления данных в буфере. Если буфер расположен в памяти адаптера и к нему нет прямого доступа со стороны процессора, метод выполняет пересылку данных из временного буфера в нужный участок памяти адаптера. Это может потребовать времени, количество которого можно оценить при помощи поля dwUnlockTransferRate описателя параметров буфера.
Play - запуск звучания буфера
HRESULT IDirectSoundBuffer::Play ( DWORD Reserved, DWORD Priority, DWORD Flags );
- Reserved - зарезервированный параметр, должен иметь нулевое значение;
- Priority - приоритет данного источника звука, если при создании буфера был указан флаг отложенного размещения DSBCAPS_LOCDEFER. В этом случае подсистема стремится обеспечить аппаратное смешивание для источников с наибольшими значениями приоритета. Если флаг отложенного размещения не был указан, этот параметр должен иметь нулевое значение;
- Flags - флаги, уточняющие операцию. Имена констант флагов имеют префикс DSBPLAY_:
LOOPING |
Циклическое проигрывание. Буфер проигрывается непрерывно, по достижении конца позиция воспроизведения автоматически перебрасывается в начало. Первичный буфер может работать только в циклическом режиме |
---|---|
LOCHARDWARE |
Требует обязательного аппаратного смешивания для данного источника. При нехватке ресурсов аппаратного смешивания и отсутствии условий досрочного завершения звучания операция завершается с ошибкой |
LOCSOFTWARE |
Разрешает программное смешивание для данного источника. Выбор конкретного способа смешивания остается за подсистемой |
Флаги условий досрочного завершения звучания гарантируют, что источник будет смешиваться аппаратно, однако при нехватке ресурсов его звучание может быть досрочно прекращено. Имена констант имеют префикс DSBPLAY_TERMINATEBY_:
TIME |
Разрешает прекращать звучание источника, которому осталось меньше всего времени до естественного завершения |
---|---|
DISTANCE |
Разрешает прекращать звучание источника, наиболее удаленного от слушателя и имеющего в свойствах флаг DSBCAPS_ MUTE3DBYDISTANCE. Допускается только для буферов пространственных источников. Этот флаг несовместим с предыдущим |
PRIORITY |
Разрешает прекращать звучание источника, если требуется запустить источник более высокого приоритета (параметр Priority) |
Флаги LOCHARDWARE и LOCSOFTWARE являются взаимоисключающими. Эти два флага, а также флаги TERMINATEBY допускаются только для буферов с отложенным размещением (флаг DSBCAPS_LOCDEFER).
Метод запускает проигрывание буфера с текущей позиции воспроизведения. Для приложений, не имеющих прямого доступа к первичному буферу, первичный буфер создается и запускается автоматически при запуске первого вторичного буфера. Приложения, работающие на уровне доступа к первичному буферу, должны сами запускать его, указывая флаг LOOPING.
Приложения более низкого уровня доступа могут использовать метод для гарантированного запуска первичного буфера, чтобы при отсутствии активных вторичных буферов адаптер не выключался (в первичном буфере в это время - ). Это позволяет избежать лишних включений/выключений адаптера и связанных с этим помех. По сути, активность первичного буфера для таких приложений зависит от внутреннего счетчика, к которому каждый последующий запуск любого буфера добавляет единицу, а остановка любого буфера - вычитает ее. При нулевом значении счетчика первичный буфер останавливается и адаптер выключается.
Если буфер уже активизирован, метод лишь обновляет флаги режимов проигрывания, не затрагивая текущей позиции буфера.
Перед первым с момента создания объекта устройства обращением к методу Play должен быть установлен уровень взаимодействия методом IDirectSound::SetCooperativeLevel. В противном случае метод Play завершается успешно, но звук появляется только после установки уровня взаимодействия.
Stop - прекращение проигрывания буфера
HRESULT IDirectSoundBuffer::Stop ();
Метод останавливает проигрывание буфера. Для вторичного буфера сохраняется текущая позиция воспроизведения. Для первичного буфера, к которому приложение имеет уровень прямого доступа, позиция при остановке сбрасывается в нуль. Для приложений менее высоких уровней взаимодействия метод уменьшает счетчик активности первичного буфера на единицу; то же самое происходит и при остановке любого из вторичных буферов. При достижении счетчиком нулевого значения первичный буфер останавливается. При ненулевом значении счетчика и отсутствии активных вторичных буферов в первичном буфере проигрывается тишина.
GetStatus - запрос состояния буфера
HRESULT IDirectSoundBuffer::GetStatus ( DWORD *Status );
- Status - указатель переменной, в которую будут возвращены флаги состояния буфера. Имена констант флагов имеют префикс DSBSTATUS_:
LOCHARDWARE |
Используется аппаратное смешивание |
---|---|
LOCSOFTWARE |
Используется программное смешивание |
PLAYING |
Буфер активен (проигрывается) |
LOOPING |
Буфер проигрывается циклически. Может быть установлен только при наличии предыдущего флага |
TERMINATED |
Проигрывание буфера досрочно прекращено из-за нехватки аппаратных ресурсов |
BUFFERLOST |
Буфер потерян |
Флаги LOCHARDWARE и LOCSOFTWARE являются взаимоисключающими. Они, а также флаг TERMINATED могут быть установлены только для буферов с отложенным размещением (флаг DSBCAPS_LOCDEFER).
GetCurrentPosition - запрос текущих позиций буфера
HRESULT IDirectSoundBuffer::GetCurrentPosition ( DWORD *PlayCursor, DWORD *WriteCursor );
- PlayCursor - указатель переменной, в которой будет возвращено смещение позиции воспроизведения буфера;
- WriteCursor - указатель переменной, в которой будет возвращено смещение позиции записи (обновления данных) буфера.
Позиции в буфере возвращаются в виде байтовых смещений. Если какая-либо позиция не нужна, соответствующий указатель может быть нулевым.
Позиция записи обычно опережает позицию воспроизведения на 10-15 мс. Участок буфера начиная с позиции записи и предшествующей (по правилу закольцовки буфера) позиции воспроизведения считается уже проигранным и может быть обновлен в любой момент.
SetCurrentPosition - установка позиции воспроизведения буфера
HRESULT IDirectSoundBuffer::SetCurrentPosition ( DWORD PlayPosition );
- PlayPosition - новая позиция воспроизведения в виде байтового смещения от начала буфера.
Метод допустим только для вторичных буферов. Проигрывание первичного буфера всегда начинается с его начала.
GetFrequency - запрос частоты дискретизации
HRESULT IDirectSoundBuffer::GetFrequency ( DWORD *Frequency );
- Frequency - указатель переменной, в которой будет возвращено текущее значение частоты дискретизации буфера (в Гц, или отсчетах в секунду).
SetFrequency - установка частоты дискретизации
HRESULT IDirectSoundBuffer::SetFrequency ( DWORD Frequency );
- Frequency - новое значение частоты дискретизации буфера (в Гц, или отсчетов в секунду). Должно быть в диапазоне между DSBFREQUENCY_MIN (обычно 100) и DSBFREQUENCY_MAX (обычно 100000). Значение DSBFREQUENCY_ORIGINAL возвращает частоту, заданную исходным форматом при создании буфера.
Метод применим только к вторичным буферам. Изменение частоты дискретизации изменяет скорость воспроизведения звука и, как следствие, его высоту. Воспроизведение звука с частотой дискретизации, отличной от используемой в первичном буфере, требует интерполяции отсчетов и при отсутствии средств аппаратного ускорения может заметно увеличить накладные расходы системы.
GetPan - запрос текущего положения источника на панораме
HRESULT IDirectSoundBuffer::GetPan ( LONG *Pan );
- Pan - указатель переменной, в которой возвращается текущее положение источника звука на стереопанораме. Смысл значения раскрыт в описании метода SetPan.
SetPan - установка текущего положения источника на панораме
HRESULT IDirectSoundBuffer::SetPan ( LONG Pan );
- Pan - новое положение источника на стереопанораме. Знак значения задает ослабляемый канал (минус - правый, плюс - левый), абсолютная величина - степень ослабления громкости канала в сотых долях децибела. Значение DSBPAN_CENTER (нуль) означает центральное положение (оба канала имеют полную громкость). Значения DSBPAN_LEFT (минус 10000) и DSBPAN_RIGHT (10000) дают ослабление правого/левого канала на 100 дБ.
GetVolume - запрос уровня громкости источника
HRESULT IDirectSoundBuffer::GetVolume ( LONG *Volume );
- Volume - указатель переменной, в которой возвращается текущее значение уровня громкости источника. Смысл значения раскрыт в описании метода SetVolume.
SetVolume - установка уровня громкости источника
HRESULT IDirectSoundBuffer::SetVolume ( LONG Volume );
- Volume - новое значение уровня громкости источника в сотых долях децибела. Уровень 0 дБ (DSBVOLUME_MAX) соответствует исходному уровню цифрового сигнала в буфере. Определена также константа DSBVOLUME_MIN (минус 10000), задающая уровень -100 дБ. Усиление сигнала относительно исходного уровня в данной реализации не поддерживается.
Интерфейс IDirectSoundCapture
Обслуживает объекты устройств захвата (записи). Поскольку процессы воспроизведения и захвата в большинстве своем симметричны, методы интерфейса подобны методам IDirectSound. Разница заключается лишь в типизации параметров и структур.
Интерфейс содержит следующие методы:
Initialize |
Инициализация объекта устройства |
---|---|
GetCaps |
Запрос параметров и возможностей устройства |
CreateCaptureBuffer |
Создание буфера захвата |
Initialize - инициализация объекта устройства
HRESULT IDirectSoundCapture::Initialize ( LPCGUID GUID );
Подобен методу IDirectSound::Initialize.
GetCaps - запрос параметров устройства
HRESULT IDirectSoundCapture::GetCaps ( DSCCAPS *Caps );
- Caps - указатель описателя параметров устройства захвата (структура DSCCAPS).
Подобен методу IDirectSound::GetCaps.
CreateCaptureBuffer - создание буфера захвата
HRESULT IDirectSoundCapture::CreateCaptureBuffer ( DSCBUFFERDESC *BufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *Buffer, UNKNOWN *Outer );
- BufferDesc - указатель описателя создаваемого буфера (структура DSCBUFFERDESC);
- Buffer - указатель переменной, в которой будет возвращен указатель созданного объекта буфера;
- Outer - указатель объекта интерфейса IUnknown. Не используется, должен иметь нулевое значение.
Подобен методу IDirectSound::CreateSoundBuffer. В отличие от процесса воспроизведения, допускающего смешивание нескольких источников, процесс захвата допускает наличие только одного буфера, и здесь нет разделения на первичный и вторичные буферы.
Интерфейс IDirectSoundCaptureBuffer
Обслуживает буфер захвата. Подобен интерфейсу IDirectSoundBuffer, однако для каждого устройства может существовать только один буфер захвата; и нет разделения на первичный и вторичные буферы.
Интерфейс содержит следующие методы:
Initialize |
Инициализация объекта буфера |
---|---|
GetCaps |
Запрос параметров буфера |
GetFormat |
Запрос формата буфера |
GetCurrentPosition |
Запрос текущих позиций в буфере |
GetStatus |
Запрос состояния буфера |
Lock |
Запрос обновления данных в буфере |
Unlock |
Завершение обновления данных в буфере |
Start |
Запуск захвата в буфер |
Stop |
Остановка захвата в буфер |
Initialize - инициализация объекта буфера
HRESULT IDirectSoundCaptureBuffer::Initialize ( DIRECTSOUNDCAPTURE *CaptureDev, LPCDSCBUFFERDESC BufferDesc );
- CaptureDev - указатель объекта устройства захвата;
- BufferDesc - указатель описателя буфера (структура DSCBUFFERDESC).
Метод подобен IDirectSoundBuffer::Initialize.
GetCaps - запрос параметров буфера
HRESULT IDirectSoundCaptureBuffer::GetCaps ( DSCBCAPS *Caps );
- Caps - указатель описателя параметров буфера захвата (структура DSCBCAPS).
Метод подобен IDirectSoundBuffer::GetCaps.
GetFormat - запрос формата буфера
HRESULT IDirectSoundCaptureBuffer::GetFormat ( WAVEFORMATEX *Format, DWORD SizeAllocated, DWORD *SizeWritten );
- Format - указатель области памяти для описателя формата (структура WAVEFORMATEX), который будет заполнен параметрами формата буфера, или;
- SizeAllocated - размер в байтах области памяти описателя;
- SizeWritten - указатель переменной, в которую будет занесен реальный размер заполненного описателя, или нуль, если размер не требуется;
Метод подобен IDirectSoundBuffer::GetFormat.
GetCurrentPosition - запрос текущих позиций буфера
HRESULT IDirectSoundCaptureBuffer::GetCurrentPosition ( DWORD *CaptureCursor, DWORD *ReadCursor );
- CaptureCursor - указатель переменной, в которой будет возвращено смещение позиции захвата буфера;
- ReadCursor - указатель переменной, в которой будет возвращено смещение позиции чтения буфера.
Метод подобен IDirectSoundBuffer::GetCurrentPosition. Разница заключается в изменении положения позиций: при захвате позиция чтения следует за позицией захвата, ее.
GetStatus - запрос состояния буфера
HRESULT IDirectSoundCaptureBuffer::GetStatus ( DWORD *Status );
- Status - указатель переменной, в которую будут возвращены флаги состояния буфера. Имена констант флагов имеют префикс DSCBSTATUS_:
CAPTURING |
Буфер активен (идет захват) |
---|---|
LOOPING |
Буфер зациклен (по достижении конца позиция захвата перебрасывается в начало) |
Метод подобен IDirectSoundBuffer::GetStatus.
Lock - открывание процедуры извлечения данных
HRESULT IDirectSoundCaptureBuffer::Lock ( DWORD Cursor, DWORD Bytes, LPVOID *Ptr1, DWORD *Bytes1, LPVOID *Ptr2, DWORD *Bytes2, DWORD Flags );
- Cursor - смещение (относительно начала буфера) участка, к которому запрашивается прямой доступ;
- Bytes - размер участка в байтах;
- Ptr1, Ptr2 - указатели переменных, в которых будут возврашены указатели частей полученного участка памяти;
- Bytes1, Bytes2 - указатели переменных, в которых будут возвращены размеры частей полученного участка памяти;
- Flags - флаги, уточняющие операцию. Имена констант флагов имеют префикс DSCBLOCK_:
ENTIREBUFFER |
Запрашивается доступ ко всей доступной для чтения части буфера. Параметр Bytes игнорируется |
---|
Метод подобен IDirectSoundBuffer::Lock.
Unlock - завершение процедуры извлечения данных
HRESULT IDirectSoundCaptureBuffer::Unlock ( VOID *Ptr1, DWORD Bytes1, VOID *Ptr2, DWORD Bytes2 );
- Ptr1, Ptr2 - указатели прочитанных участков буфера, возвращенные ранее методом Lock;
- Bytes1, Bytes2 - количества байтов, реально считанных из участков
Метод подобен IDirectSoundBuffer::Unlock.
Start - запуск захвата в буфер
HRESULT IDirectSoundCaptureBuffer::Start ( DWORD Flags );
- Flags - флаги, уточняющие операцию. Имена констант флагов имеют префикс DSCBSTART_:
LOOPING |
Циклический захват - позиция захвата по достижении конца буфера автоматически перебрасывается в начало. Захват продолжается до тех пор, пока не будет остановлен методом Stop |
---|
Метод подобен IDirectSoundBuffer::Play.
Stop - остановка захвата в буфер
HRESULT IDirectSoundCaptureBuffer::Stop ();
Метод подобен IDirectSoundBuffer::Stop.
Интерфейс IDirectSoundNotify
Обслуживает объекты уведомления. Имеет единственный метод SetNotificationPositions.
SetNotificationPositions - заказ позиций уведомления
HRESULT IDirectSoundNotify::SetNotificationPositions ( DWORD NumOfNotifies, LPCDSBPOSITIONNOTIFY Notifies );
- NumOfNotifies - количество заказанных описателей уведомления в массиве Notifies;
- Notifies - массив описателей уведомления, по одному на позицию.
Метод описывает позиции воспроизведения или захвата, по достижении которых должны быть установлены указанные объекты событий. В момент выполнения метода буфер должен быть неактивным (остановленным).
Если заказано уведомление в случае остановки буфера (DSBPN_OFFSETSTOP), такой описатель должен быть в массиве последним.
Повторные вызовы метода заменяют список уведомлений для буфера.
Если поддержка DirectSound для устройства реализована в виде драйвера VxD, уведомление доступно только для буферов, размещенных в основной памяти. При поддержке в виде драйвера WDM буфер может находиться в памяти адаптера.
Интерфейс IKsPropertySet
Обслуживает объекты звуковых буферов DirectSound и является частью модели WDM KS (Windows Driver Model, Kernel Streaming). Позволяет связывать с источниками звука различные наборы свойств.
Интерфейс запрашивается у объекта буфера воспроизведения или записи посредством метода QueryInterface и содержит следующие методы:
QuerySupport |
Опрос наличия поддержки указанного набора свойств |
---|---|
Get |
Опрос свойства |
Set |
Установка свойства |
QuerySupport - опрос наличия поддержки свойства
HRESULT IKsPropertySet::QuerySupport ( REFGUID SetGUID, ULONG Index, ULONG *Support );
- SetGUID - ссылка (в C++) или адрес (C) GUID опрашиваемого набора свойств;
- Index - индекс (номер) нужного свойства в наборе - начиная с нуля;
- Support - указатель переменной, в которой возвращается информация о поддержке указанного свойства.
При успешном завершении метод возвращает в переменную Support информацию о поддержке указанного свойства и о возможных операциях с ним. При отсутствии указанного набора или свойства возвращается нуль, иначе возвращается комбинация из флагов KSPROPERTY_SUPPORT_GET (свойство допускает опрос) и KSPROPERTY_SUPPORT_SET (свойство допускает установку).
При отсутствии поддержки свойства или набора некоторые реализации могут возвращать код ошибки E_NOTIMPL.
Get - запрос свойства
HRESULT IKsPropertySet::Get ( REFGUID SetGUID, ULONG Index, VOID *Instance, ULONG InstanceLength, VOID *Property, ULONG PropertyLength, ULONG *BytesReturned );
- SetGUID - ссылка (в C++) или адрес (C) GUID опрашиваемого набора свойств;
- Index - индекс (номер) нужного свойства в наборе - начиная с нуля;
- Instance - указатель области данных, уточняющих операцию запроса свойства;
- InstanceLength - размер области уточняющих данных;
- Property - указатель области данных, в которой возвращается описание свойства;
- PropertyLength - размер области данных для описания свойства;
- BytesReturned - указатель переменной, в которой возвращается количество байтов, реально занесенное в область описания свойства.
Возвращаемое методом значение и содержимое области описания свойства зависят от реализации набора свойств и самого опрашиваемого свойства.
Set - установка свойства
HRESULT IKsPropertySet::Set ( REFGUID SetGUID, ULONG Index, VOID *Instance, ULONG InstanceLength, VOID *Property, ULONG PropertyLength, );
- SetGUID - ссылка (в C++) или адрес (C) GUID опрашиваемого набора свойств;
- Index - индекс (номер) нужного свойства в наборе - начиная с нуля;
- Instance - указатель области данных, уточняющих операцию установки свойства;
- InstanceLength - размер области уточняющих данных;
- Property - указатель области данных, содержащей описание свойства.
- PropertyLength - размер области описания свойства.
Недостатки DirectSound
В основном недостатки DirectSound являются обратной стороной достоинств подсистемы. Ориентация на существующие звуковые ускорители впоследствии может оказаться несовместимой с новыми моделями аппаратуры, а текущая модель DirectSound - неэффективной.
Упор на работу с короткими звуками несколько затрудняет работу с длительными звуковыми потоками, однако это достаточно легко преодолевается.
Типичные применения DirectSound
Основным применением, ради которого разрабатывалась подсистема, являются игры. Созданная модель позволяет очень удобно описать множество источников звука, снабдить их параметрами, разместить в пространстве, а в ходе игры - оперативно включать и выключать их, управлять параметрами звучания, изменяя звуковую картину.
DirectSound находит также массовое применение в программах синтеза звука и музыки, которым средства подсистемы позволяют описывать звучания отдельных музыкальных инструментов или их частей, а затем в реальном времени сводить эти звучания воедино.
Благодаря возможности смешивания звука и более эффективного использования аппаратуры, с помощью DirectSound удобно реализуется одновременное воспроизведение длительных звуковых фрагментов и управление ими. Например, естественно строятся программы имитации звуковых микшерных пультов, аппаратуры для дискотек и тому подобные средства управления звуком.
Оптимизация вывода звука в DirectSound
Оптимизация форматов
Поскольку звучания всех вторичных буферов в конечном итоге смешиваются в первичном буфере адаптера, подсистеме или адаптеру приходится преобразовывать звуковые данные к единому формату. Адаптеры с поддержкой аппаратного смешивания всегда делают это с достаточной скоростью, обеспечивая одновременное звучание заявленного количества каналов. Однако при программном смешивании все преобразования выполняет сама подсистема, а это требует интерполяции отсчетов и специального способа суммирования (так называемое суммирование с насыщением). Все это отнимает изрядную долю процессорного времени и при количестве каналов больше нескольких единиц начинает заметно сказываться на скорости работы системы.
Для предотвращения роста накладных расходов при программном смешивании рекомендуется придерживаться унифицированных форматов первичного и вторичных буферов. Более всего времени отнимает преобразование частоты дискретизации, затем количества каналов; преобразование разрядности отсчетов почти не вносит задержек.
Для оптимизации работы ускорителя полезно определить методом IDirectSound::GetCaps аппаратно поддерживаемые форматы и использовать только их.
Помимо этого для коротких и постоянных по составу звуков рекомендуется создавать буферы статического типа.
Непрерывная работа первичного буфера
По умолчанию DirectSound включает воспроизведение первичного буфера при активизации одного или нескольких вторичных буферов и выключает первичный буфер, когда активных вторичных буферов не остается. При большой динамичности чередования звуков из вторичных буферов рост частоты включений/выключений может вызвать существенные накладные расходы. Кроме того, многие звуковые адаптеры издают достаточно громкие щелчки при запуске и остановке процесса воспроизведения.
Указанных проблем можно избежать, установив первичный буфер в режим непрерывной работы при помощи метода Play. С этого момента буфер будет непрерывно; при отсутствии активных вторичных буферов в первичном буфере будет только (нулевые, нейтральные звуковые отсчеты). Перевод буфера в стандартный режим осуществляется методом Stop.
Оставить комментарий
Комментарии
я обычный пользователь, сама никак не разберусь...
а где dsound.h dsound.lib и демонстрационная программа ?