Программирование звука в DirectSound
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.
Пример программы, использующей DirectSound
В качестве примера приведена программа DSMix, демонстрирующая получение сложного звучания из набора простых звуков. Методом копирования программа создает три вторичных буфера, ссылающихся на один и тот же участок памяти, содержащий фрагмент звучания ноты «до» первой октавы органа. Для второго и третьего буферов частота дискретизации сдвигается на 4 и 7 полутонов соответственно, так что частоты трех буферов образуют мажорный аккорд на ноте «до». При этом все три буфера разделяют один и тот же звуковой фрагмент; разница высоты достигается разной скоростью проигрывания потока.
Три переключателя в диалоговом окне программы независимо включают и выключают звучание каждого из буферов, добавляя в аккорд соответствующую ступень или удаляя ее.
Программа работает с устройством на приоритетном уровне взаимодействия, чтобы иметь возможность установить формат 44100/16/моно. Стандартный формат 22 050/8/стерео дает слишком низкое качество звучания.
Для оптимизации аппаратного ускорения вторичные буферы сделаны статическими. Звуковой фрагмент зацикливается, так что образуется непрерывное органное звучание.
Для простоты программа не обрабатывает ситуацию потери буферов, поэтому в случае конфликта с приложением высшего уровня взаимодействия звучание прекратится до перезапуска каждого из буферов.
Звук выводится на стандартное системное устройство DirectSound.
Программа написана на C++ в среде Microsoft Visual C++ 4.2.
КомпьютерПресс 12'2000