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常數的位 OR。
[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
格式描述元的指標。 這個參數必須指向一個類型為 (或) 的顯示格式描述元。 如需詳細資訊,請參閱<備註>。
[in] AudioSessionGuid
會話 GUID 的指標。 此參數指向 GUID 值,識別資料流程所屬的音訊會話。 如果 GUID 識別先前已開啟的會話,方法會將資料流程新增至該會話。 如果 GUID 無法識別現有的會話,方法會開啟新的會話,並將資料流程新增至該會話。 資料流程會在其存留期內維持相同會話的成員。 將此參數設定為 Null 相當於將指標傳遞至GUID_Null值。
傳回值
如果方法成功,它會傳回 S_OK。 如果失敗,可能的傳回碼包括但不限於下表所示的值。
傳回碼 | Description |
---|---|
|
IAudioClient物件已經初始化。 |
|
已設定AUDCLNT_STREAMFLAGS_LOOPBACK旗標,但端點裝置是擷取裝置,而不是轉譯裝置。 |
|
注意 適用于 Windows 7 和更新版本。
|
|
注意 適用于 Windows 7 和更新版本。
|
|
表示進程傳遞持續時間超過 CPU 使用量上限。 音訊引擎會藉由維護進程傳遞持續時間超過 CPU 使用量上限的次數,來追蹤 CPU 使用量。 最大 CPU 使用量會計算為引擎週期性的百分比。 百分比值是系統 CPU 節流值, (介於 10% 和 90%) 的範圍內。 如果找不到此值,則會使用預設值 40% 來計算最大 CPU 使用量。 |
|
音訊端點裝置已解除叢集,或音訊硬體或相關聯的硬體資源已重新設定、停用、移除或無法使用。 |
|
端點裝置已在使用中。 裝置正以獨佔模式使用,或裝置正用於共用模式,而呼叫端要求以獨佔模式使用裝置。 |
|
方法無法建立轉譯或擷取裝置的音訊端點。 如果音訊端點裝置已解除叢集,或音訊硬體或相關聯的硬體資源已重新設定、停用、移除,或無法供使用,就會發生這種情況。 |
|
注意 適用于 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 參數) 不是音訊畫面的整數數目,此方法會將要求的緩衝區大小四捨五入到下一個整數數目的畫面格。
在 初始化 呼叫之後,用戶端應該呼叫 IAudioClient::GetBufferSize 方法,以取得端點緩衝區的精確大小。 在每個處理階段期間,用戶端將需要實際的緩衝區大小,以計算要傳送到緩衝區或從緩衝區傳輸多少資料。 用戶端會呼叫 IAudioClient::GetCurrentPadding 方法來判斷緩衝區中目前有多少資料可供處理。
若要達到用戶端應用程式與音訊端點裝置之間的最小資料流程延遲,用戶端執行緒應該在與音訊引擎執行緒相同的期間執行。 引擎執行緒的期間是固定的,無法由用戶端控制。 讓用戶端的期間小於引擎的期間,不必要地增加處理器上的用戶端執行緒負載,而不會改善延遲或減少緩衝區大小。 若要判斷引擎執行緒的期間,用戶端可以呼叫 IAudioClient::GetDevicePeriod 方法。 若要將緩衝區設定為引擎執行緒所需的最小大小,用戶端應該呼叫 Initialize ,並將 hnsBufferDuration 參數設定為 0。 在 初始化 呼叫之後,用戶端可以藉由呼叫 IAudioClient::GetBufferSize來取得產生的緩衝區大小。
用戶端可以選擇要求大於嚴格必要條件的緩衝區大小,讓計時問題很少或不存在。 增加緩衝區大小不一定會增加資料流程延遲。 對於轉譯資料流程,透過緩衝區的延遲只會由用戶端的寫入指標與引擎的讀取指標分隔來決定。 對於擷取資料流程,透過緩衝區的延遲只會由引擎的寫入指標與用戶端讀取指標之間的分隔來決定。
回送旗標 (AUDCLNT_STREAMFLAGS_LOOPBACK) 啟用音訊回送。 用戶端只能在具有共用模式資料流程的轉譯端點上啟用音訊回送。 音訊回送主要是為了支援聲場回音取消 (AEC) 。
AEC 用戶端需要轉譯端點,以及從音訊引擎擷取輸出資料流程的能力。 引擎的輸出資料流程是音訊裝置透過喇叭播放的全域混合。 如果啟用音訊回送,用戶端可以藉由呼叫 IAudioClient::GetService 方法來開啟全域音訊混合的擷取緩衝區,以取得轉譯資料流程物件上的 IAudioCaptureClient 介面。 如果未啟用音訊回送,則嘗試在轉譯資料流程上開啟擷取緩衝區將會失敗。 擷取緩衝區中的回送資料是裝置格式,用戶端可以藉由查詢裝置 的 PKEY_AudioEngine_DeviceFormat 屬性來取得。
在Windows 10之前的 Windows 版本上,提取模式擷取用戶端不會在以事件驅動緩衝 (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 Service Pack 1 版本中,此旗標在共用模式和獨佔模式中運作;應用程式可以設定此旗標,以啟用擷取資料流程的事件緩衝處理。 如需擷取音訊資料流程的詳細資訊,請參閱 擷取資料流程。
若要啟用事件驅動緩衝,用戶端必須提供事件控制碼給系統。 在 呼叫IAudioClient::Start 方法以啟動資料流程之前,用戶端必須呼叫 IAudioClient::SetEventHandle 方法來設定事件控制碼。 當資料流程執行時,系統會定期發出事件訊號,向用戶端指出音訊資料可供處理。 在處理傳遞之間,用戶端執行緒會藉由呼叫 WaitForSingleObject之類的同步處理函式,在事件控制碼上等候。 如需同步處理函式的詳細資訊,請參閱 Windows SDK 檔。
對於使用事件驅動緩衝的共用模式資料流程,呼叫端必須同時將 hnsPeriodicity 和 hnsBufferDuration 設定為 0。 Initialize方法會根據音訊引擎的排程週期來決定要配置的緩衝區大小。 雖然用戶端的緩衝區處理執行緒是事件驅動,但如先前所述,基本緩衝區管理程式並未變更。 每次執行緒喚醒時,它都應該呼叫 IAudioClient::GetCurrentPadding ,以判斷要寫入轉譯緩衝區或從擷取緩衝區讀取多少資料。 相較于 Initialize 方法針對使用事件驅動緩衝的獨佔模式資料流程配置的兩個緩衝區,共用模式資料流程需要單一緩衝區。
針對使用事件驅動緩衝的獨佔模式資料流程,呼叫端必須指定 hnsPeriodicity 和 hnsBufferDuration的非零值,而且這兩個參數的值必須相等。 Initialize方法會為數據流配置兩個緩衝區。 每個緩衝區的持續時間都等於 hnsBufferDuration 參數的值。 在轉譯資料流程的 初始化 呼叫之後,呼叫端應該先填滿這兩個緩衝區的第一個,再啟動資料流程。 對於擷取資料流程,緩衝區一開始是空的,而呼叫端應該假設每個緩衝區都會保持空白,直到發出該緩衝區的事件發出訊號為止。 當資料流程執行時,系統會替代將一個緩衝區或其他緩衝區傳送至用戶端,這種形式的雙緩衝處理稱為「ping-ponging」。 每次用戶端收到來自系統 (緩衝區時,系統會透過發出事件) 發出訊號,用戶端必須處理整個緩衝區。 例如,如果用戶端從不符合緩衝區大小的 IAudioRenderClient::GetBuffer 方法要求封包大小,則方法會失敗。 不需要呼叫 IAudioClient::GetCurrentPadding 方法,因為封包大小必須一律等於緩衝區大小。 相較于先前所討論的緩衝模式,事件驅動、獨佔模式資料流程的延遲會直接取決於緩衝區大小。
如 音訊會話中所述,包含轉譯資料流程的會話預設行為是其音量和靜音設定會在應用程式重新開機時保存。 AUDCLNT_STREAMFLAGS_NOPERSIST旗標會覆寫預設行為,並讓設定非持續性。 此旗標不會影響包含擷取資料流程的會話,這些會話的設定永遠不會持續。 此外,包含回送資料流程的會話設定, (使用 AUDCLNT_STREAMFLAGS_LOOPBACK 旗標初始化的資料流程) 不是持續性的。
只有連線到轉譯端點裝置的會話可以有持續性磁片區和靜音設定。 要新增至會話的第一個資料流程會決定會話的設定是否為持續性。 因此,如果在初始化第一個資料流程期間設定AUDCLNT_STREAMFLAGS_NOPERSIST或AUDCLNT_STREAMFLAGS_LOOPBACK旗標,會話的設定不會持續。 否則,它們是持續性的。 其持續性不受後續在會話物件存留期間新增或移除的其他資料流程影響。
呼叫 Initialize 已成功初始化 IAudioClient 介面實例之後,初始化相同介面實例 的後續 Initialize 呼叫將會失敗,並傳回錯誤碼E_ALREADY_INITIALIZED。
如果初始化的初始呼叫失敗,後續的 Initialize呼叫可能會失敗,並傳回錯誤碼E_ALREADY_INITIALIZED,即使介面尚未初始化也一樣。 如果發生這種情況,請先釋放IAudioClient介面,然後從MMDevice API取得新的IAudioClient介面,然後再再次呼叫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並將AudioClientProperties的bIsOffload參數設定為 TRUE,則必須在StreamFlags參數中將AUDCLNT_STREAMFLAGS_EVENTCALLBACK旗標指定為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 |
標頭 | audioclient.h |