close

Вход

Забыли?

вход по аккаунту

?

из ПЗ (2)

код для вставкиСкачать
 Подсистема DirectSound обеспечивает приложениям практически непосредственный доступ к аппаратуре звукового адаптера. Приложению предоставляется модель современного звукового адаптера, предельно приближенная к реальности, с минимальным уровнем абстракции.
Подсистема DirectSound построена по объектно-ориентированному принципу в соответствии с моделью COM (Component Object Model - модель объектов-компонентов, или составных объектов) и состоит из набора интерфейсов. Каждый интерфейс отвечает за объект определенного типа - устройство, буфер, службу уведомления и т.п. По сути, интерфейс представляет собой обычный набор управляющих функций, или методов, организованных в класс объектно-ориентированного языка.
Назначение DirectSound - исключительно эффективный вывод звука, а операции по преобразованию форматов остаются в ведении приложений. DirectSound снимает это ограничение, позволяя приложению просто задавать несколько источников звука, которые будут проиграны одновременно. Количество таких источников ограничено только доступной памятью и быстродействием аппаратуры (есть упоминание).
DirectSound использует возможности аппаратуры там, где это можно, а в остальных случаях выполняет нужную работу на программном уровне.
Большинство существующих звуковых адаптеров использует для обмена звуком с центральным процессором звуковые буферы, представляющие собой участок памяти, в который заносятся звуковые данные. Обычно буфер является кольцевым, то есть указатель текущей позиции при достижении конца буфера автоматически перебрасывается на его начало, совершая внутри буфера круговое движение. Пример кольцевого буфера показан на рисунке 1. Рис. 1. Кольцевой буфер
В зависимости от размещения и способа управления различают аппаратные (hardware) и программные (software) буферы. Аппаратным называют буфер, к которому адаптер имеет прямой доступ; такой буфер располагается либо в памяти самого адаптера, либо в основной памяти с обращением через DMA или Bus Mastering. Программные буферы всегда располагаются в основной памяти и управляются центральным процессором, адаптер к таким буферам прямого доступа не имеет.
Первичный и вторичные буферы
Если в архитектуре адаптера один из аппаратных буферов является основным, его называют первичным (primary). Остальные буферы, занимающие подчиненное положение, называются вторичными (secondary). Обычно звуки из вторичных буферов смешиваются воедино в первичном буфере, откуда и поступают на ЦАП адаптера. Микширование подразумевает, что если записать звук в то место первичного звукового буфера, куда уже был записан другой звук, то будут воспроизводиться оба звука одновременно.
Рис. 2. Микширование вторичных звуковых буферов в первичный звуковой буфер
Чаще всего приложению не требуется использовать первичный буфер. В типовой схеме взаимодействия для каждого источника звука создается свой вторичный буфер (в DirectSound часто отождествляются понятия <источник звука> и <вторичный звуковой буфер>). Даже если смешивание выполняет DirectSound - оно осуществляется на уровне ядра (VxD или системно).
В исключительных случаях возможен прямой доступ к первичному буферу. При этом запрещается использование вторичных буферов - то есть приложение теряет возможность описывать независимые источники звука. Однако первичный буфер имеет фиксированный размер, выбираемый драйвером DirectSound. Статические и потоковые буферы
Вторичный буфер может быть статическим (static) и потоковым (streaming). Статические буферы предназначены для постоянных звуков, цифровое представление которых не меняется либо меняется достаточно редко. Потоковые буферы ориентированы на часто изменяемые звуки, как правило - на представление длительного звукового потока, который по частям "прогоняется" через буфер.
Статические и потоковые буферы различаются только тем, что подсистема старается в первую очередь делать аппаратными статические буферы, загружая их в память адаптера. Таким образом, постоянные и короткие звуки оказываются в распоряжении адаптера, и достаточно лишь дать команду, чтобы они включились в общее звучание.
При желании приложение может явно указывать при создании буфера тип памяти для его размещения.
Потоковое воспроизведение звука
Если нужно проиграть длинный звуковой файл, необходимо использовать механизм потокового воспроизведения звука. Секрет заключается в использовании зацикленного воспроизведения, обеспечивающего непрерывный звук без пауз, и постоянную загрузку новых звуковых данных на замену тем, которые уже были воспроизведены.
Данный механизм заключается в установке нескольких маркеров в звуковом буфере. Когда воспроизводимый звук проходит один из этих маркеров, мы получаем сигнал, что пришло время загружать следующую порцию звуковых данных, вместо воспроизведенной. На рисунке 3 показан звуковой буфер с четырьмя потоковыми маркерами, сообщающими когда должны быть загружены новые звуковые данные.
Рис.3. Иллюстрация осуществления механизма потокового воспроизведения звука.
Для потокового воспроизведения звука сначала загружается звуковыми данными весь буфер (столько данных, сколько поместится в буфер). Запускается воспроизведение звука и происходит ожидание, пока не будет достигнут первый маркер. В этот момент следующий небольшой фрагмент звуковых данных вставляется в только что воспроизведенную секцию. Воспроизведение продолжается, пока не будет достигнут второй маркер, и в этой точке новые данные загружаются в только что воспроизведенный фрагмент.
Процесс продолжается пока весь звук не будет загружен и воспроизведен до того места, где сработает маркер, оповещающий об остановке звука. Если звук зациклен, воспроизведение продолжается путем повторения последовательности действий, описанной выше.
Управление режимами вторичных буферов
Поскольку каждый вторичный буфер описывает независимый источник звука, подсистема предоставляет средства управления режимами звучания источника. Для базовых источников DirectSound доступно управление громкостью, панорамой и частотой дискретизации; для источников DirectSound3D еще и пространственными координатами, направленностью и скоростью движения.
Для изменения набора необходимо уничтожить буфер и создать его заново. Изменение частоты воспроизведения звукового буфера меняет высоту звука.
Позиции в буфере
DirectSound использует для адресации в звуковых буферах понятие текущих позиций, или курсоров. Различают позицию записи/воспроизведения, отслеживающую проигрывание звука из буфера в адаптер или запись звука из адаптера в буфер, и позицию доступа, отслеживающую чтение/запись (обмен данными) между приложением и буфером. В первичной англоязычной документации первая позиция называется Play/Capture Position, а вторая - Read/Write Position. Уровни взаимодействия
DirectSound вводит четыре уровня взаимодействия (cooperation levels) приложений между собой и звуковым адаптером.
* Обычный (normal) уровень фиксирует формат первичного буфера адаптера. Форматы вторичных буферов преобразуются в этот формат, и при переключении приложений подсистеме нет необходимости изменять формат первичного буфера. * Приоритетный (priority) уровень позволяет приложению устанавливать формат первичного буфера и уплотнять внутреннюю память адаптера - то есть предоставляет приоритетный доступ к аппаратным ресурсам, когда окно приложения становится активным (foreground). Если происходит переключение между приложениями этого уровня, установившими различные форматы первичного буфера, - подсистема вынуждена переключать форматы, для чего необходим перезапуск адаптера, нередко порождающий щелчки и тому подобные помехи. * Исключительный (exclusive) уровень подобен приоритетному, но на время активности окна приложения ему предоставляется исключительный доступ к адаптеру, и звучание источников всех остальных приложений заглушается (но не останавливается). * Уровень доступа к первичному буферу (write-primary) разрешает приложению прямую запись в первичный буфер адаптера.
Потеря буферов
Когда приложение высшего уровня становится активным, звучание всех вторичных буферов приложений более низких уровней останавливается, а сами буферы помечаются как потерянные. Это происходит потому, что подсистема не может правильно отслеживать текущие позиции во вторичных буферах, не имея доступа к первичному буферу адаптера. И наоборот, когда приложение высшего уровня становится неактивным, его первичный буфер также помечается как потерянный.
Приложения получают сообщение о потере буферов при попытках обращения к ним в виде кода ошибки DSERR_BUFFERLOST. Все приложения должны корректно обрабатывать эту ситуацию и выполнять восстановление потерянных буферов.
Поэтому при создании звукового буфера лучше использовать флаг DSBCAPS_LOCKSOFTWARE, говорящий DirectSound о необходимости использовать системную память. Это позволит не беспокоиться о потере ресурсов.
Эмуляция
Подсистема DirectSound может обходиться без поддержки со стороны драйвера. В этом случае нужная функциональность эмулируется через MME - традиционную звуковую подсистему Windows. Однако такая эмуляция крайне неэффективна, поскольку при этом подсистеме DirectSound приходится эмулировать первичный буфер в обычной памяти, смешивать в нем звуки из вторичных буферов, затем представлять его в виде цепочки буферов, передаваемых драйверу MME, который, в свою очередь, разбивает их на фрагменты и переносит в звуковой буфер адаптера. Отметим, что без наличия специализированного DirectSound-драйвера невозможно получить высший (write-primary) уровень взаимодействия с адаптером.
Уведомление о наступлении событий
Событием в подсистеме DirectSound считается достижение одной из заданных позиций в звуковом буфере. Для запроса уведомления о наступлении таких событий приложение может использовать специальный интерфейс IDirectSoundNotify, создавая соответствующие ему следящие объекты. При достижении указанных позиций следящий объект активизирует (set) заданные объекты события (event objects), которые могут быть опрошены приложением непосредственно, либо может быть создана отдельная задача (thread), ожидающая активизации одного или нескольких объектов событий.
1.3 Общая схема взаимодействия программы и 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 объекты буферов, а затем - объекты устройств.
Документ
Категория
Рефераты
Просмотров
9
Размер файла
557 Кб
Теги
1/--страниц
Пожаловаться на содержимое документа