訓練
學習路徑
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
在罕見的情況下,特製化音訊應用程式可能需要使用 IKsControl 介面來存取 DeviceTopology API 或 MMDevice API未公開之音頻適配卡的特定硬體功能。 IKsControl 介面可讓使用者模式應用程式使用核心串流 (KS) 裝置的屬性、事件和方法。 在音訊應用程式中,對 KS 屬性的關注是主要的。 IKsControl 介面可與 DeviceTopology API 和 MMDevice API 搭配使用,以存取音訊適配卡的 KS 屬性。
IKsControl 介面主要供撰寫控制面板應用程式來管理其音訊硬體的硬體廠商使用。 IKsControl 對於未繫結至特定硬體裝置的一般用途音訊應用程式,較不有用。 原因是硬體廠商經常實作專屬機制來存取其裝置的音訊屬性。 相較於 DeviceTopology API 隱藏硬體特定的驅動程式問題,並提供相對統一的介面來存取音訊屬性,應用程式則使用 IKsControl 直接與驅動程式通訊。 如需 IKsControl的詳細資訊,請參閱 Windows DDK 檔。
如 裝置拓撲所述,配接器裝置拓撲中的子單位可能支援下表左欄中顯示的一或多個函式特定控制介面。 表格右欄中的每個項目都是對應至左側控制介面的 KS 屬性。 控制項介面可讓您方便存取 屬性。 大部分音訊驅動程式都會使用 KS 屬性來代表其音訊配接器拓撲中子單位(也稱為 KS 節點)的函式特定處理功能。 如需 KS 屬性和 KS 節點的詳細資訊,請參閱 Windows DDK 檔。
控制介面 | KS 屬性 |
---|---|
IAudioAutoGainControl | KSPROPERTY_AUDIO_AGC |
IAudioBass | KSPROPERTY_AUDIO_BASS |
IAudioChannelConfig | KSPROPERTY_AUDIO_CHANNEL_CONFIG |
IAudioInputSelector | KSPROPERTY_AUDIO_MUX_SOURCE |
IAudioLoudness | KSPROPERTY_AUDIO_音量增強 |
IAudioMidrange | KSPROPERTY_AUDIO_MID |
IAudioMute | KSPROPERTY_AUDIO_MUTE |
IAudioOutputSelector | KSPROPERTY_AUDIO_DEMUX_DEST |
IAudioPeakMeter | KSPROPERTY_AUDIO_PEAKMETER |
IAudioTreble | KSPROPERTY_AUDIO_TREBLE |
IAudioVolumeLevel | KSPROPERTY_AUDIO_音量級別 |
IDeviceSpecificProperty | KSPROPERTY_AUDIO_DEV_SPECIFIC |
某些音訊配接器的拓撲可能包含具有上表未列出的 KS 屬性的子單位。 例如,假設特定子單位對 IPart::GetSubType 方法的呼叫會擷取 GUID 值KSNODETYPE_TONE。 這個子類型 GUID 表示子單位支援下列一或多個 KS 屬性:
此清單中的前三個屬性可以透過上表中出現的控件介面來存取,但 deviceTopology API 中沒有對應控件介面的KSPROPERTY_AUDIO_BASS_BOOST屬性。 不過,如果子單位支援 屬性,應用程式可以使用 IKsControl 介面來存取此屬性。
需要執行下列步驟,才能存取子類型子單位的 KSPROPERTY_AUDIO_BASS_BOOST 屬性KSNODETYPE_TONE:
下列程式碼範例會從副類型為 KSNODETYPE_TONE 的子單位中擷取 KSPROPERTY_AUDIO_BASS_BOOST 屬性值,
//-----------------------------------------------------------
// This function calls the IKsControl::Property method to get
// the value of the KSPROPERTY_AUDIO_BASS_BOOST property of
// a subunit. Parameter pPart should point to a part that is
// a subunit with a subtype GUID value of KSNODETYPE_TONE.
//-----------------------------------------------------------
#define PARTID_MASK 0x0000ffff
#define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
const IID IID_IKsControl = __uuidof(IKsControl);
HRESULT GetBassBoost(IMMDeviceEnumerator *pEnumerator,
IPart *pPart, BOOL *pbValue)
{
HRESULT hr;
IDeviceTopology *pTopology = NULL;
IMMDevice *pPnpDevice = NULL;
IKsControl *pKsControl = NULL;
LPWSTR pwszDeviceId = NULL;
if (pEnumerator == NULL || pPart == NULL || pbValue == NULL)
{
return E_INVALIDARG;
}
// Get the topology object for the adapter device that contains
// the subunit represented by the IPart interface.
hr = pPart->GetTopologyObject(&pTopology);
EXIT_ON_ERROR(hr)
// Get the device ID string that identifies the adapter device.
hr = pTopology->GetDeviceId(&pwszDeviceId);
EXIT_ON_ERROR(hr)
// Get the IMMDevice interface of the adapter device object.
hr = pEnumerator->GetDevice(pwszDeviceId, &pPnpDevice);
EXIT_ON_ERROR(hr)
// Activate an IKsControl interface on the adapter device object.
hr = pPnpDevice->Activate(IID_IKsControl, CLSCTX_ALL, NULL, (void**)&pKsControl);
EXIT_ON_ERROR(hr)
// Get the local ID of the subunit (contains the KS node ID).
UINT localId = 0;
hr = pPart->GetLocalId(&localId);
EXIT_ON_ERROR(hr)
KSNODEPROPERTY_AUDIO_CHANNEL ksprop;
ZeroMemory(&ksprop, sizeof(ksprop));
ksprop.NodeProperty.Property.Set = KSPROPSETID_Audio;
ksprop.NodeProperty.Property.Id = KSPROPERTY_AUDIO_BASS_BOOST;
ksprop.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
ksprop.NodeProperty.NodeId = localId & PARTID_MASK;
ksprop.Channel = 0;
// Send the property request.to the device driver.
BOOL bValue = FALSE;
ULONG valueSize;
hr = pKsControl->KsProperty(
&ksprop.NodeProperty.Property, sizeof(ksprop),
&bValue, sizeof(bValue), &valueSize);
EXIT_ON_ERROR(hr)
*pbValue = bValue;
Exit:
SAFE_RELEASE(pTopology)
SAFE_RELEASE(pPnpDevice)
SAFE_RELEASE(pKsControl)
CoTaskMemFree(pwszDeviceId);
return hr;
}
在上述程式代碼範例中,GetBassBoost 函式會採用下列三個參數:
pEnumerator
指向音訊端點列舉器的 IMMDeviceEnumerator 介面。pPart
指向子單位的 IPart 介面,其子單位的子類型為 KSNODETYPE_TONE。pbValue
指向函式寫入屬性值的 BOOL 變數。程式只會在呼叫 IPart::GetSubType 之後呼叫 GetBassBoost,並判斷子單位的子類型KSNODETYPE_TONE。 屬性值會是 TRUE,前提是已啟用低音提升。 如果低音提升功能被停用,則是 FALSE。
在 GetBassBoost 函式的開頭,呼叫 IPart::GetTopologyObject 方法會取得包含KSNODETYPE_TONE子單位之配接器裝置的 IDeviceTopology 介面。 IDeviceTopology::GetDeviceId 方法呼叫會擷取識別配接器裝置的裝置標識符字串。 IMMDeviceEnumerator::GetDevice 方法呼叫會採用裝置標識符字串作為輸入參數,並擷取配接器裝置的 IMMDevice 介面。 接下來,IMMDevice::Activate 方法呼叫會擷取子單位的 IKsControl 介面。 如需 IKsControl 介面的詳細資訊,請參閱 Windows DDK 檔。
接下來,上述程式碼範例會建立描述低音增強屬性的 KSNODEPROPERTY_AUDIO_CHANNEL 結構。 程序代碼範例會將結構的指標傳遞至 IKsControl::KsProperty 方法,該方法會使用 結構中的資訊來擷取屬性值。 如需 KSNODEPROPERTY_AUDIO_CHANNEL 結構和 IKsControl::KsProperty 方法的詳細資訊,請參閱 Windows DDK 檔。
音訊硬體通常會將個別的低音提升狀態指派給音訊串流中的每個通道。 原則上,某些通道可以啟用低音提升,並停用其他通道。 KSNODEPROPERTY_AUDIO_CHANNEL 結構包含一個成員 Channel,該成員指定通道號碼。 如果數據流包含 N 通道,則通道編號是從 0 到 N- 1。 上述程式代碼範例只會取得通道 0 的 bass-boost 屬性值。 此實作會隱含假設所有通道的Bass-boost屬性會統一設定為相同的狀態。 因此,讀取通道 0 的低音增強屬性就足以確定數據流的低音增強屬性值。 為了符合此假設,設定bass-boost屬性的對應函式會將所有通道設定為相同的低音提升屬性值。 這些是合理的慣例,但並非所有硬體廠商都一定遵循這些慣例。 例如,廠商可能會提供控制面板應用程式,只針對驅動全範圍喇叭的通道啟用低音提升功能。 (全範圍喇叭能夠播放從低音到高音的全範圍音效。在此情況下,上述程式代碼範例所擷取的屬性值可能無法準確地表示數據流的低音提升狀態。
使用上表所列控件介面的用戶端可以呼叫 IPart::RegisterControlChangeCallback 方法,以在控件參數的值變更時註冊通知。 請注意,IKsControl 介面不提供類似的方法,讓客戶端在屬性值變更時註冊通知。 如果 IKsControl 確實支援屬性變更通知,當另一個應用程式變更屬性值時,它可能會通知應用程式。 不過,相較於透過 IPart IPart 通知監視的較常用控件,IKsControl 所管理的屬性主要是供硬體廠商使用,而且這些屬性可能只由廠商撰寫的控制面板應用程式變更。 如果應用程式必須偵測另一個應用程式所做的屬性變更,則可以透過 IKsControl定期輪詢屬性值來偵測變更。
訓練
學習路徑
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
文件
DeviceTopology API - Win32 apps
DeviceTopology API
受保護的使用者模式音訊 (PUMA) - Win32 apps
Windows Vista 引進了受保護的使用者模式音訊 (PUMA),受保護環境 (PE) 中的使用者模式音訊引擎,為音訊處理和轉譯提供更安全的環境。
裝置拓撲