設定和查詢音訊設備模組
本文說明如何從 UWP app 傳送命令和接收來自音訊裝置模組的變更通知。 音訊裝置模組可能是硬體效果處理單位,或是音訊驅動程式所定義的任何其他音訊組態模組。 這項功能的設計目的是要讓模組提供者建立UWP應用程式,讓用戶能夠控制及取得在 DSP 中執行的音訊處理模組的狀態資訊。 若要使用本文所示的音訊裝置模組 API,您必須在應用程式套件指令清單中指定受限制 的 audioDeviceConfiguration 功能。
取得 AudioDeviceModulesManager 類別的實例
本文中顯示的所有音訊裝置模組作業一開始都是取得 AudioDeviceModulesManager 的實例。 請先呼叫 MediaDevice 類別的靜態 GetDefaultAudioRenderId 方法來執行此動作。 這會傳回預設音訊轉譯裝置的標識符,然後傳遞至 AudioDeviceModulesManager 的建構函式,以建立與音訊裝置相關聯的類別實例。
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
查詢已安裝的音訊設備模組
藉由呼叫 AudioDeviceModulesManager 類別的 FindAll 來查詢所有已安裝的音訊設備模組。 呼叫 FindAllById 並傳入所要求模組的識別碼,以查詢特定一組音訊設備模組。 下列範例會定義一組模組的標識符、呼叫 FindAllById 來擷取 AudioDeviceModule 物件的清單,然後將每個模組的詳細數據列印到偵錯輸出。
C#
public const string Contoso_AudioDeviceModuleId = "F72E09C3-FEBA-4C50-93BE-2CA56123AF09";
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
var modules = audioModuleManager.FindAllById(Contoso_AudioDeviceModuleId);
foreach (var module in modules)
{
var classId = module.ClassId;
var name = module.DisplayName;
var minorVersion = module.MinorVersion;
var majorVersion = module.MajorVersion;
var instanceId = module.InstanceId;
Debug.WriteLine($"{classId} : {name} : {minorVersion} : {majorVersion} : {instanceId}");
}
將命令傳送至音訊裝置模組並接收結果數據
在 AudioDeviceModule 物件上呼叫 SendCommandAsync,將命令傳送至音訊裝置模組。 SendCommandAsync 方法會採用位元組陣列作為自變數。 此位元組數位通常包含命令標識碼,後面接著與命令相關聯的數據,但命令格式和值完全由廠商定義,而且會由系統視為透明。
SendCommandAsync 方法會傳回異步操作,完成時會傳回代表命令結果的ModuleCommandResult物件。 Status 屬性包含列舉值,指出系統是否能夠執行命令。 這不一定表示音訊設備模組能夠順利執行命令。 Result 屬性包含音訊設備模組傳回的位元組陣列,以指出命令的狀態。 一般而言,這會是指出成功或失敗的值,後面接著命令的數據結果。 如同模組命令,模組回應格式和值是廠商定義的。
下列範例會呼叫 FindAllAsync 來擷取一組音訊裝置模組。 DataWriter 可用來建立包含範例命令和數據的位元組陣列。 呼叫 SendCommandAsync 來傳送命令緩衝區,並在異步操作完成之後傳回 ModuleCommandResult 。 如果命令執行成功, DataReader 會先用來讀取模組傳回的整數狀態值。 如果此值是廠商定義的成功值,則應用程式會讀取並使用其餘的結果數據,例如更新UI。
C#
public const byte Contoso_ReverbLevel_Command = 30;
public const byte Contoso_SendCommand_Success = 99;
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
var modules = audioModuleManager.FindAllById(Contoso_AudioDeviceModuleId);
foreach (var module in modules)
{
var writer = new Windows.Storage.Streams.DataWriter();
writer.WriteByte(Contoso_ReverbLevel_Command);
writer.WriteByte(100);
var command = writer.DetachBuffer();
var result = await module.SendCommandAsync(command);
if (result.Status == SendCommandStatus.Success)
{
using (DataReader reader = DataReader.FromBuffer(result.Result))
{
int bufferStatus = reader.ReadInt32();
if (bufferStatus == Contoso_SendCommand_Success)
{
byte[] data = { 0, 0 };
reader.ReadBytes(data);
// Do something with returned data, such as update UI
}
}
}
}
修改音訊設備模組時接收通知
應用程式可以藉由註冊 ModuleNotificationReceived 事件來接收音訊裝置模組更新時的通知。
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
audioModuleManager.ModuleNotificationReceived += AudioModuleManager_ModuleNotificationReceived;
修改與目前音訊裝置相關聯的任何音訊裝置模組時,將會引發ModuleNotificationReceived。 若要判斷事件是否與特定模塊相關聯,請藉由存取傳遞至事件處理程式的 AudioDeviceModuleNoticiationEventArgs 的 Module 屬性,然後檢查識別模組的 ClassId 屬性,以取得 AudioDeviceModule 的實例。 與事件相關聯的數據會以儲存在事件自變數的 NotificationData 屬性中的位元組陣列的形式傳遞。 如同命令和結果,傳回位元組數位的格式是廠商定義的。 在下列範例中,如果通知數據的第一個字節包含模組殘響層級設定的範例值,則會讀取數據,並用來更新UI。
C#
public const byte Contoso_ReverbLevel_Data = 25;
C#
private void AudioModuleManager_ModuleNotificationReceived(AudioDeviceModulesManager sender, AudioDeviceModuleNotificationEventArgs args)
{
if (args.Module.ClassId == Contoso_AudioDeviceModuleId)
{
// Get the coefficient data from the reverb module.
using (DataReader reader = DataReader.FromBuffer(args.NotificationData))
{
// read notification data.
byte item = reader.ReadByte();
// if reverb coefficient data are changed.
if (item == Contoso_ReverbLevel_Data)
{
// read the new value
byte[] data = { 0 };
reader.ReadBytes(data);
ReverbLevelSlider.Value = data[0];
}
}
}
}