Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #44, ИЮЛЬ 2004 г.

Direct Sound в объятиях программиста

Фленов Михаил

Спецвыпуск Xakep, номер #044, стр. 044-014-3


Следующим этапом вызывается функция SetCooperativeLevel, которая устанавливает приоритет обработки нашего интерфейса. Не будем скромничать и используем приоритетный уровень - DSSCL_PRIORITY. Если жадность превышает все пределы, то можно повысить приоритет до максимального - DSSCL_WRITEPRIMARY. Разумеется, для особо тихих и скромных существует DSSCL_NORMAL.

После этого создаем буфер для хранения звуковых данных функцией CreateSoundBuffer. В программе должен быть как минимум один первичный буфер - запросим именно его. Для этого понадобится структура типа TDSBufferDesc (в нашем случае это будет переменная dsbd), которую мы заполним нулями, чтобы в ней не оказалось какого-нибудь мусора. Нужно правильно указать два свойства:

- dwSize, размер структуры;

- dwFlags, флаги.

В качестве флага мы указываем DSBCAPS_PRIMARYBUFFER, что соответствует первичному буферу.

Теперь эту структуру необходимо указать в качестве первого параметра функции CreateSoundBuffer, а через второй параметр мы получим указатель на интерфейс буфера. Через этот интерфейс можно будет начинать и завершать воспроизведение.

В отличие от классической mmsystem, в Direct Sound буфер циклический, и при достижении конца чтение или запись будет происходить с самого начала. Раньше приходилось выделять два буфера, последовательно заполнять их данными и переключать воспроизведение/запись между ними. Теперь этого делать не надо, хотя вторичные буферы всегда могут пригодиться для других целей.

Если представить себе буфер данных в виде круга (см. рисунок «Буфер обмена»), то точка воспроизведения как бы движется по часовой стрелке. В этот момент мы можем без проблем пополнять буфер данными в точку записи.

Прямая работа с первичным буфером очень важна, поскольку он поддерживает больше всего фильтров и эффектов. Правда, при большой нагрузке звук может выводиться с задержкой. Из этой ситуации есть выход – использовать вторичные буферы и потом микшировать их в один первичный.

Интерфейс буфера должен знать, какие данные нужно воспроизводить, поэтому нужно указать формат с помощью функции SetFormat. В данном случае будет проигрываться WAV-файл, и в эту функцию придется передать структуру типа TWaveFormatEx с правильно заполненными значениями формата. Если ты кодил под MMSystem или читал мою книгу «Библия Delphi», то структура будет уже знакомой и не вызовет проблем.

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

Играй, невеселая песня моя

Скромный интерфейс нашего примера будет содержать всего два элемента - поле ввода для указания имени файла и кнопку для воспроизведения. По нажатию кнопки нужно написать следующий код:

Назад на стр. 044-014-2  Содержание  Вперед на стр. 044-014-4