共用方式為


設定和查詢音訊設備模組

本文說明如何從 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。 若要判斷事件是否與特定模塊相關聯,請藉由存取傳遞至事件處理程式的 AudioDeviceModuleNoticiationEventArgsModule 屬性,然後檢查識別模組的 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];
            }
        }
    }
}