Метод IAudioClient::Initialize (audioclient.h)
Метод Initialize инициализирует аудиопоток.
Синтаксис
HRESULT Initialize(
[in] AUDCLNT_SHAREMODE ShareMode,
[in] DWORD StreamFlags,
[in] REFERENCE_TIME hnsBufferDuration,
[in] REFERENCE_TIME hnsPeriodicity,
[in] const WAVEFORMATEX *pFormat,
[in] LPCGUID AudioSessionGuid
);
Параметры
[in] ShareMode
Режим общего доступа для подключения. С помощью этого параметра клиент сообщает обработчику звука, хочет ли он предоставить доступ к устройству конечной точки аудио с другими клиентами. Клиент должен задать этому параметру одно из следующих значений перечисления AUDCLNT_SHAREMODE :
AUDCLNT_SHAREMODE_EXCLUSIVE
AUDCLNT_SHAREMODE_SHARED
[in] StreamFlags
Флаги для управления созданием потока. Клиент должен задать этому параметру значение 0 или побитовое ЗНАЧЕНИЕ ИЛИ одной или нескольких констант AUDCLNT_STREAMFLAGS_XXX или констант AUDCLNT_SESSIONFLAGS_XXX.
[in] hnsBufferDuration
Емкость буфера в виде значения времени. Этот параметр имеет тип REFERENCE_TIME и выражается в 100-наносекундных единицах. Этот параметр содержит размер буфера, который вызывающий объект запрашивает для буфера, который звуковое приложение будет совместно использовать с обработчиком звука (в режиме общего доступа) или с устройством конечной точки (в монопольном режиме). Если вызов завершается успешно, метод выделяет буфер, который меньше этого размера. Дополнительные сведения о REFERENCE_TIME см. в документации по Windows SDK. Дополнительные сведения о требованиях к буферизации см. в разделе Примечания.
[in] hnsPeriodicity
Период устройства. Этот параметр может быть ненулевым только в монопольном режиме. В общем режиме всегда устанавливайте для этого параметра значение 0. В монопольном режиме этот параметр задает запрошенный период планирования для последовательных обращений к буферу со стороны конечного устройства аудио. Если запрошенный период устройства находится за пределами диапазона, заданного минимальным периодом устройства и максимальным периодом системы, метод зажимает период в этом диапазоне. Если этот параметр равен 0, метод задает для периода устройства значение по умолчанию. Чтобы получить период устройства по умолчанию, вызовите метод IAudioClient::GetDevicePeriod . Если установлен флаг потока AUDCLNT_STREAMFLAGS_EVENTCALLBACK и AUDCLNT_SHAREMODE_EXCLUSIVE задан как ShareMode, то значение hnsPeriodicity должно быть ненулевым и равно hnsBufferDuration.
[in] pFormat
Указатель на дескриптор формата. Этот параметр должен указывать на допустимый дескриптор формата типа WAVEFORMATEX (или WAVEFORMATEXTENSIBLE). Дополнительные сведения см. в подразделе "Примечания".
[in] AudioSessionGuid
Указатель на GUID сеанса. Этот параметр указывает на значение GUID, определяющее звуковой сеанс, к которому принадлежит поток. Если GUID идентифицирует ранее открытый сеанс, метод добавляет поток в этот сеанс. Если GUID не идентифицирует существующий сеанс, метод открывает новый сеанс и добавляет поток в этот сеанс. Поток остается членом одного и того же сеанса на протяжении всего времени его существования. Присвоение этому параметру значения NULL эквивалентно передаче указателя на значение GUID_NULL.
Возвращаемое значение
Если метод завершается успешно, возвращает значение S_OK. В случае сбоя возможные коды возврата включают, но не ограничиваются ими, значения, показанные в следующей таблице.
Код возврата | Описание |
---|---|
|
Объект IAudioClient уже инициализирован . |
|
Флаг AUDCLNT_STREAMFLAGS_LOOPBACK установлен, но устройство конечной точки является устройством захвата, а не устройством отрисовки. |
|
Примечание Применяется к Windows 7 и более поздних версий.
|
|
Примечание Применяется к Windows 7 и более поздних версий.
|
|
Указывает, что длительность прохода процесса превысила максимальную загрузку ЦП. Звуковой модуль отслеживает загрузку ЦП, сохраняя количество раз, когда длительность прохода процесса превышает максимальную загрузку ЦП. Максимальная загрузка ЦП рассчитывается в процентах от периодичности ядра. Процентное значение — это значение регулирования ЦП системы (в диапазоне от 10 % до 90 %). Если это значение не найдено, то для вычисления максимальной загрузки ЦП используется значение по умолчанию 40 %. |
|
Устройство конечной точки звука было отключено, или звуковое оборудование или связанные аппаратные ресурсы были перенастроены, отключены, удалены или иным образом стали недоступными для использования. |
|
Устройство конечной точки уже используется. Либо устройство используется в монопольном режиме, либо устройство используется в общем режиме, и вызывающий запрос на использование устройства в монопольном режиме. |
|
Методу не удалось создать конечную точку звука для отрисовки или устройства захвата. Это может произойти, если устройство конечной точки звука было отключено или звуковое оборудование или связанные аппаратные ресурсы были перенастроены, отключены, удалены или иным образом стали недоступными для использования. |
|
Примечание Применяется к Windows 7 и более поздних версий.
|
|
Звуковой модуль (общий режим) или устройство конечной точки аудио (монопольный режим) не поддерживают указанный формат. |
|
Вызывающий объект запрашивает монопольное использование устройства конечной точки, но пользователь отключил монопольное использование устройства. |
|
Флаг AUDCLNT_STREAMFLAGS_EVENTCALLBACK задан, но параметры hnsBufferDuration и hnsPeriodicity не равны. |
|
Аудиослужба Windows не запущена. |
|
Параметр pFormat имеет значение NULL. |
|
Параметр pFormat указывает на недопустимое описание формата; или флаг AUDCLNT_STREAMFLAGS_LOOPBACK установлен, но ShareMode не равен AUDCLNT_SHAREMODE_SHARED; или флаг AUDCLNT_STREAMFLAGS_CROSSPROCESS установлен, но ShareMode равен AUDCLNT_SHAREMODE_EXCLUSIVE.
Предыдущий вызов SetClientProperties был выполнен с недопустимой категорией для аудио-потоков или потоков отрисовки. |
|
Недостаточно памяти. |
Комментарии
После активации интерфейса IAudioClient на устройстве конечной точки аудио клиент должен успешно вызвать метод Initialize только один раз, чтобы инициализировать звуковой поток между клиентом и устройством. Клиент может подключаться напрямую к звуковому оборудованию (монопольный режим) или косвенно через обработчик звука (общий режим). В вызове Initialize клиент указывает формат звуковых данных, размер буфера и звуковой сеанс для потока.
Если поток инициализирован для управления событиями и в режиме общего доступа, ShareMode устанавливается в AUDCLNT_SHAREMODE_SHARED, а один из заданных флагов потока включает AUDCLNT_STREAMFLAGS_EVENTCALLBACK. Для такого потока связанное приложение также должно получить дескриптор, выполнив вызов IAudioClient::SetEventHandle. Когда пора снять поток с учета, обработчик аудиоданных может использовать дескриптор для освобождения объектов потока. Сбой вызова IAudioClient::SetEventHandle перед освобождением объектов потока может вызвать задержку в несколько секунд (период ожидания), пока звуковой модуль ожидает доступного дескриптора. По истечении времени ожидания звуковой модуль освобождает объекты потока.
Успешная ли попытка создать поток в монопольном режиме, зависит от нескольких факторов, включая доступность устройства и управляемые пользователем параметры, управляющие работой устройства в монопольном режиме. Дополнительные сведения см. в разделе Потоки в монопольном режиме.
Объект IAudioClient поддерживает ровно одно подключение к звуковому движунку или звуковому оборудованию. Это соединение длится в течение всего времени существования объекта IAudioClient .
Клиент должен вызывать следующие методы только после вызова Метода Initialize:
- IAudioClient::GetBufferSize
- IAudioClient::GetCurrentPadding
- IAudioClient::GetService
- IAudioClient::GetStreamLatency
- IAudioClient::Reset
- IAudioClient::SetEventHandle
- IAudioClient::Start
- IAudioClient::Stop
Перед вызовом Initialize для настройки подключения в общем или монопольном режиме клиент может вызвать метод IAudioClient::IsFormatSupported , чтобы определить, поддерживает ли звуковой модуль или устройство конечной точки звука определенный формат в этом режиме. Перед открытием подключения в общем режиме клиент может получить формат микса звукового модуля, вызвав метод IAudioClient::GetMixFormat .
Буфер конечной точки, общий между клиентом и обработчиком звука, должен быть достаточно большим, чтобы предотвратить сбои в звуковом потоке между обработкой передачи клиентом и обработчиком звука. Для конечной точки отрисовки поток клиента периодически записывает данные в буфер, а поток звукового модуля периодически считывает данные из буфера. Для конечной точки отслеживания поток подсистемы периодически записывает данные в буфер, а поток клиента периодически считывает данные из буфера. В любом случае, если периоды клиентского потока и потока подсистемы не равны, буфер должен быть достаточно большим, чтобы вместить более длительный из двух периодов, не допуская сбоев.
Клиент задает размер буфера с помощью параметра hnsBufferDuration . Клиент отвечает за запрос буфера, который достаточно велик, чтобы гарантировать, что сбои не могут возникать между периодическими проходами обработки, которые он выполняет в буфере. Аналогичным образом, метод Initialize гарантирует, что буфер никогда не будет меньше минимального размера буфера, необходимого для обеспечения того, чтобы не возникали сбои между периодическими проходами обработки, которые поток подсистемы выполняет в буфере. Если клиент запрашивает размер буфера, который меньше минимального требуемого размера буфера звукового модуля, метод устанавливает размер буфера на этот минимальный размер буфера, а не на размер буфера, запрошенный клиентом.
Если клиент запрашивает размер буфера (с помощью параметра hnsBufferDuration ), который не является целым числом аудиокадров, метод округляет запрошенный размер буфера до следующего целого числа кадров.
После вызова Initialize клиент должен вызвать метод IAudioClient::GetBufferSize , чтобы получить точный размер буфера конечной точки. Во время каждого этапа обработки клиенту потребуется фактический размер буфера, чтобы вычислить объем данных, передаваемых в буфер или из буфера. Клиент вызывает метод IAudioClient::GetCurrentPadding , чтобы определить, сколько данных в буфере в настоящее время доступно для обработки.
Чтобы обеспечить минимальную задержку потока между клиентским приложением и устройством конечной точки аудио, поток клиента должен выполняться в тот же период, что и поток звукового модуля. Период потока подсистемы фиксирован и не может контролироваться клиентом. Уменьшение периода клиента по сравнению с периодом ядра без необходимости увеличивает нагрузку клиентского потока на процессор без увеличения задержки или уменьшения размера буфера. Чтобы определить период потока подсистемы, клиент может вызвать метод IAudioClient::GetDevicePeriod . Чтобы задать для буфера минимальный размер, необходимый потоку подсистемы, клиент должен вызвать Метод Initialize с параметром hnsBufferDuration , равным 0. После вызова Initialize клиент может получить размер результирующего буфера, вызвав IAudioClient::GetBufferSize.
Клиент может запросить размер буфера, который больше, чем то, что строго необходимо, чтобы временные сбои были редкими или отсутствуют. Увеличение размера буфера не обязательно увеличивает задержку потока. Для потока отрисовки задержка через буфер определяется исключительно разделением между указателем записи клиента и указателем чтения подсистемы. Для потока записи задержка через буфер определяется исключительно разделением между указателем записи подсистемы и указателем чтения клиента.
Флаг замыкания на себя (AUDCLNT_STREAMFLAGS_LOOPBACK) включает замыкания звука на себя. Клиент может включить замыкания звука только на конечной точке отрисовки с потоком в общем режиме. Обратная связь звука предоставляется в основном для поддержки подавления акустического эха (AEC).
Для клиента AEC требуется как конечная точка отрисовки, так и возможность захвата выходного потока из звукового модуля. Поток вывода подсистемы — это глобальный набор, который звуковое устройство воспроизводит через динамики. Если включена обратная связь звука, клиент может открыть буфер записи для глобального аудиомиксического набора, вызвав метод IAudioClient::GetService для получения интерфейса IAudioCaptureClient в объекте потока отрисовки. Если замыкание звука на себя не включено, попытка открыть буфер записи в потоке отрисовки завершится ошибкой. Данные замыкания на себя в буфере записи приведены в формате устройства, который клиент может получить, запросив свойство PKEY_AudioEngine_DeviceFormat устройства.
В версиях Windows до Windows 10 клиент записи в режиме извлечения не будет получать события, если поток инициализирован с помощью буферизации на основе событий (AUDCLNT_STREAMFLAGS_EVENTCALLBACK) и включен замыкание на себя (AUDCLNT_STREAMFLAGS_LOOPBACK). Если поток открывается с такой конфигурацией, вызов Initialize завершается успешно, но соответствующие события не вызываются для уведомления клиента отслеживания каждый раз, когда буфер становится готовым к обработке. Чтобы обойти эту проблему, инициализируйте поток отрисовки в режиме, управляемом событиями. Каждый раз, когда клиент получает событие для потока отрисовки, он должен сигнализировать клиенту записи о запуске потока отслеживания, который считывает следующий набор примеров из буфера конечной точки отслеживания. В Windows 10 соответствующие дескрипторы событий теперь задаются для активных потоков с поддержкой замыкания на себя.
Обратите внимание, что все потоки должны быть открыты в режиме общего доступа, так как потоки в монопольном режиме не могут работать в режиме замыкания на себя. Дополнительные сведения о замыканиях на себя звука см. в разделе Запись с замыкания на себя.
Флаг AUDCLNT_STREAMFLAGS_EVENTCALLBACK указывает, что обработка буфера звука клиентом будет управляться событиями. WASAPI поддерживает управляемую событиями буферизацию, чтобы обеспечить обработку потоков в общем и монопольном режиме с низкой задержкой.
Первоначальный выпуск Windows Vista поддерживает управляемую событиями буферизацию (то есть использование флага AUDCLNT_STREAMFLAGS_EVENTCALLBACK) только для отрисовки потоков.
В первоначальном выпуске Windows Vista для потоков записи флаг AUDCLNT_STREAMFLAGS_EVENTCALLBACK поддерживается только в общем режиме. Установка этого флага не влияет на потоки захвата в монопольном режиме. То есть, хотя приложение задает этот флаг в монопольном режиме с помощью вызова Initialize , приложение не будет получать события, которые обычно требуются для захвата аудиопотока. В выпуске Windows Vista с пакетом обновления 1 (SP1) этот флаг работает в режиме общего доступа и монопольном режиме; приложение может установить этот флаг, чтобы включить буферизацию событий для потоков захвата. Дополнительные сведения о записи аудиопотока см. в разделе Захват потока.
Чтобы включить управляемую событиями буферизацию, клиент должен предоставить системе дескриптор событий. После вызова Initialize и перед вызовом метода IAudioClient::Start для запуска потока клиент должен вызвать метод IAudioClient::SetEventHandle , чтобы задать дескриптор события. Во время выполнения потока система периодически сообщает о событии, указывая клиенту, что звуковые данные доступны для обработки. Между проходами обработки поток клиента ожидает дескриптора событий, вызывая функцию синхронизации, например WaitForSingleObject. Дополнительные сведения о функциях синхронизации см. в документации по Windows SDK.
Для потока общего режима, использующего управляемую событиями буферизацию, вызывающий объект должен задать для hnsPeriodicity и hnsBufferDuration значение 0. Метод Initialize определяет размер выделяемого буфера на основе периода планирования звукового модуля. Хотя поток обработки буфера клиента управляется событиями, базовый процесс управления буфером, как описано выше, неизменен. При каждом пробуждении потока он должен вызывать IAudioClient::GetCurrentPadding , чтобы определить, сколько данных нужно записать в буфер отрисовки или считывать из буфера записи. В отличие от двух буферов, которые метод Initialize выделяет для потока монопольного режима, использующего буферизацию на основе событий, для потока общего режима требуется один буфер.
Для потока в монопольном режиме, использующего буферизацию на основе событий, вызывающий объект должен указать ненулевое значение для hnsPeriodicity и hnsBufferDuration, и значения этих двух параметров должны быть равными. Метод Initialize выделяет два буфера для потока. Каждый буфер по длительности равен значению параметра hnsBufferDuration . После вызова Initialize для потока отрисовки вызывающий объект должен заполнить первый из двух буферов перед запуском потока. Для потока записи буферы изначально пусты, и вызывающий объект должен предположить, что каждый буфер остается пустым до тех пор, пока не будет показано событие для этого буфера. Во время выполнения потока система поочередно отправляет клиенту один или другой буфер . Эта форма двойной буферизации называется "пинг-понги". Каждый раз, когда клиент получает буфер из системы (что система указывает, сигнализируя о событии), клиент должен обработать весь буфер. Например, если клиент запрашивает размер пакета из метода IAudioRenderClient::GetBuffer , который не соответствует размеру буфера, метод завершается ошибкой. Вызовы метода IAudioClient::GetCurrentPadding не нужны, так как размер пакета всегда должен быть равен размеру буфера. В отличие от режимов буферизации, описанных ранее, задержка для управляемого событиями потока в монопольном режиме напрямую зависит от размера буфера.
Как описано в разделе Звуковые сеансы, поведение по умолчанию для сеанса, содержащего потоки отрисовки, заключается в том, что параметры громкости и отключения звука сохраняются при перезапуске приложения. Флаг AUDCLNT_STREAMFLAGS_NOPERSIST переопределяет поведение по умолчанию и делает параметры неперсистентными. Этот флаг не влияет на сеансы, содержащие потоки записи— параметры для этих сеансов никогда не сохраняются. Кроме того, параметры сеанса, содержащего поток замыкания на себя (поток, инициализируемый флагом AUDCLNT_STREAMFLAGS_LOOPBACK), не являются постоянными.
Только сеанс, который подключается к устройству конечной точки отрисовки, может иметь постоянный том и параметры отключения звука. Первый поток, добавляемый в сеанс, определяет, являются ли параметры сеанса постоянными. Таким образом, если флаг AUDCLNT_STREAMFLAGS_NOPERSIST или AUDCLNT_STREAMFLAGS_LOOPBACK установлен во время инициализации первого потока, параметры сеанса не сохраняются. В противном случае они являются постоянными. На их сохраняемость не влияют дополнительные потоки, которые впоследствии могут быть добавлены или удалены в течение времени существования объекта сеанса.
После успешного инициализации экземпляра интерфейса IAudioClient при вызове метода Initialize для инициализации того же экземпляра интерфейса произойдет сбой и код ошибки E_ALREADY_INITIALIZED.
Если начальный вызов метода Initialize завершается сбоем, последующие вызовы Initialize могут завершиться ошибкой и вернуть код ошибки E_ALREADY_INITIALIZED, даже если интерфейс не инициализирован. В этом случае отпустите интерфейс IAudioClient и получите новый интерфейс IAudioClient из API MMDevice перед повторным вызовом Initialize .
Примеры кода, вызывающие метод Initialize , см. в следующих разделах:
Начиная с Windows 7, приложение Initialize может возвращать AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED для устройства отрисовки или захвата. Это означает, что размер буфера, заданный вызывающим объектом в параметре hnsBufferDuration , не выравнивается. Этот код ошибки возвращается, только если вызывающий объект запросил поток в монопольном режиме (AUDCLNT_SHAREMODE_EXCLUSIVE) и буферизацию на основе событий (AUDCLNT_STREAMFLAGS_EVENTCALLBACK).Если Функция Initialize возвращает AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED, вызывающий объект должен снова вызвать Метод Initialize и указать выровненный размер буфера. Выполните указанные ниже действия.
- Вызовите IAudioClient::GetBufferSize и получите следующий по величине размер буфера (в кадрах).
- Вызовите IAudioClient::Release , чтобы освободить звуковой клиент, использованный в предыдущем вызове, который возвращал AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED.
- Вычислите выровненный размер буфера в 100 наносекундных единицах (HNS). Размер буфера —
(REFERENCE_TIME)((10000.0 * 1000 / WAVEFORMATEX.nSamplesPerSecond * nFrames) + 0.5)
. В этой формуле — это размер буфера,nFrames
полученный командой GetBufferSize. - Вызовите метод IMMDevice::Activate с параметром iid , который имеет значение REFIID IID_IAudioClient, чтобы создать новый звуковой клиент.
- Снова вызовите метод Initialize в созданном аудиоконференте и укажите новый размер буфера и периодичность.
Начиная с Windows 10, аппаратно-разгруженные аудиопотоки должны управляться событиями. Это означает, что при вызове IAudioClient2::SetClientProperties и присвоении параметру bIsOffloadобъекта AudioClientProperties значения TRUE, необходимо указать флаг AUDCLNT_STREAMFLAGS_EVENTCALLBACK в параметре StreamFlags значение IAudioClient::Initialize.
Примеры
В следующем примере кода показано, как реагировать на код возврата AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED .
#define REFTIMES_PER_SEC 10000000
HRESULT CreateAudioClient(IMMDevice* pDevice, IAudioClient** ppAudioClient)
{
if (!pDevice)
{
return E_INVALIDARG;
}
if (!ppAudioClient)
{
return E_POINTER;
}
HRESULT hr = S_OK;
WAVEFORMATEX *pwfx = NULL;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
UINT32 nFrames = 0;
IAudioClient *pAudioClient = NULL;
// Get the audio client.
CHECK_HR( hr = pDevice->Activate(
__uuidof(IAudioClient),
CLSCTX_ALL,
NULL,
(void**)&pAudioClient));
// Get the device format.
CHECK_HR( hr = pAudioClient->GetMixFormat(&pwfx));
// Open the stream and associate it with an audio session.
hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_EXCLUSIVE,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
hnsRequestedDuration,
hnsRequestedDuration,
pwfx,
NULL);
// If the requested buffer size is not aligned...
if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
{
// Get the next aligned frame.
CHECK_HR( hr = pAudioClient->GetBufferSize(&nFrames));
hnsRequestedDuration = (REFERENCE_TIME)
((10000.0 * 1000 / pwfx->nSamplesPerSec * nFrames) + 0.5);
// Release the previous allocations.
SAFE_RELEASE(pAudioClient);
CoTaskMemFree(pwfx);
// Create a new audio client.
CHECK_HR( hr = pDevice->Activate(
__uuidof(IAudioClient),
CLSCTX_ALL,
NULL,
(void**)&pAudioClient));
// Get the device format.
CHECK_HR( hr = pAudioClient->GetMixFormat(&pwfx));
// Open the stream and associate it with an audio session.
CHECK_HR( hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_EXCLUSIVE,
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
hnsRequestedDuration,
hnsRequestedDuration,
pwfx,
NULL));
}
else
{
CHECK_HR (hr);
}
// Return to the caller.
*(ppAudioClient) = pAudioClient;
(*ppAudioClient)->AddRef();
done:
// Clean up.
CoTaskMemFree(pwfx);
SAFE_RELEASE(pAudioClient);
return hr;
}
Требования
Целевая платформа | Windows |
Header | audioclient.h |