Condividi tramite


Configurare ed eseguire query sui moduli di dispositivo audio

Questo articolo illustra come inviare comandi e ricevere notifiche di modifica dai moduli di dispositivo audio da un'app UWP. Un modulo di dispositivo audio può essere un'unità di elaborazione dell'effetto hardware o qualsiasi altro modulo di configurazione audio definito da un driver audio. Questa funzionalità è stata progettata per consentire ai provider di moduli di creare app UWP che consentono agli utenti di controllare e ottenere informazioni sullo stato da un modulo di elaborazione audio in esecuzione in un DSP. Per usare le API del modulo del dispositivo audio illustrate in questo articolo, è necessario specificare la funzionalità audioDeviceConfiguration con restrizioni nel manifesto del pacchetto dell'app.

Ottenere un'istanza della classe AudioDeviceModulesManager

Tutte le operazioni del modulo del dispositivo audio illustrate in questo articolo iniziano ottenendo un'istanza di AudioDeviceModulesManager. Eseguire questa operazione chiamando prima il metodo Statico GetDefaultAudioRenderId della classe MediaDevice . In questo modo viene restituito l'ID del dispositivo di rendering audio predefinito, che viene quindi passato al costruttore per AudioDeviceModulesManager per creare un'istanza della classe associata al dispositivo audio.

C#

var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);

Eseguire una query per i moduli di dispositivo audio installati

Eseguire una query per tutti i moduli di dispositivo audio installati chiamando FindAll della classe AudioDeviceModulesManager . Eseguire una query per un set specifico di moduli di dispositivo audio chiamando FindAllById e passando l'ID dei moduli richiesti. L'esempio seguente definisce un ID per un set di moduli, chiama FindAllById per recuperare un elenco di oggetti AudioDeviceModule e quindi stampa i dettagli di ogni modulo nell'output di debug.

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}");
}

Inviare un comando a un modulo di dispositivo audio e ricevere i dati dei risultati

Inviare comandi a un modulo di dispositivo audio chiamando SendCommandAsync sull'oggetto AudioDeviceModule . Il metodo SendCommandAsync accetta una matrice di byte come argomento. In genere questa matrice di byte contiene un identificatore di comando seguito dai dati associati al comando, ma il formato e i valori del comando sono completamente definiti dal fornitore e vengono considerati trasparenti dal sistema.

Il metodo SendCommandAsync restituisce un'operazione asincrona che, al completamento, restituisce un oggetto ModuleCommandResult che rappresenta il risultato del comando. La proprietà Status contiene un valore di enumerazione che indica se il sistema è stato in grado di eseguire il comando. Ciò non indica necessariamente che il modulo del dispositivo audio è stato in grado di eseguire correttamente il comando. La proprietà Result contiene una matrice di byte restituita dal modulo del dispositivo audio per indicare lo stato del comando. In genere, si tratta di un valore che indica l'esito positivo o negativo seguito dal risultato dei dati del comando. Come per i comandi del modulo, i formati e i valori di risposta dei moduli sono definiti dal fornitore.

L'esempio seguente chiama FindAllAsync per recuperare un set di moduli di dispositivo audio. Un oggetto DataWriter viene usato per creare una matrice di byte contenente un comando e dati di esempio. SendCommandAsync viene chiamato per inviare il buffer dei comandi e, al termine dell'operazione asincrona, viene restituito un moduleCommandResult . Se l'esecuzione del comando ha avuto esito positivo, un Oggetto DataReader viene prima usato per leggere un valore di stato integer restituito dal modulo. Se questo valore è il valore di esito positivo definito dal fornitore, il resto dei dati dei risultati viene letto e usato dall'app, ad esempio per aggiornare l'interfaccia utente.

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
            }
        }
    }
}

Ricevere notifiche quando vengono modificati i moduli del dispositivo audio

Le app possono ricevere notifiche quando un modulo di dispositivo audio è stato aggiornato registrandosi per l'evento ModuleNotificationReceived .

C#

var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);

audioModuleManager.ModuleNotificationReceived += AudioModuleManager_ModuleNotificationReceived;

ModuleNotificationReceived verrà generato quando viene modificato qualsiasi modulo di dispositivo audio associato al dispositivo audio corrente. Per determinare se l'evento è associato a un modulo specifico, ottenere un'istanza di AudioDeviceModule accedendo alla proprietà Module di AudioDeviceModuleNoticiationEventArgs passata nel gestore eventi e quindi controllando la proprietà ClassId che identifica il modulo. I dati associati all'evento vengono passati come matrice di byte archiviata nella proprietà NotificationData degli argomenti dell'evento. Come per i comandi e i risultati, il formato della matrice di byte restituita è definito dal fornitore. Nell'esempio seguente, se il primo byte dei dati di notifica contiene il valore di esempio per l'impostazione del livello di riverbero del modulo, i dati vengono letti e usati per aggiornare l'interfaccia utente.

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];
            }
        }
    }
}