Configuración y consulta de módulos de dispositivo de audio
En este artículo se muestra cómo enviar comandos y recibir notificaciones de cambios de módulos de dispositivo de audio desde una aplicación para UWP. Un módulo de dispositivo de audio puede ser una unidad de procesamiento de efectos de hardware o cualquier otro módulo de configuración de audio definido por un controlador de audio. Esta característica se diseñó para permitir a los proveedores de módulos crear aplicaciones para UWP que permitan a los usuarios controlar y obtener información de estado de un módulo de procesamiento de audio que se ejecuta en un DSP. Para usar las API del módulo de dispositivo de audio que se muestran en este artículo, debe especificar la funcionalidad audioDeviceConfiguration restringida en el manifiesto del paquete de la aplicación.
Obtener una instancia de la clase AudioDeviceModulesManager
Todas las operaciones del módulo de dispositivo de audio que se muestran en este artículo comienzan obteniendo una instancia de AudioDeviceModulesManager. Para ello, llame primero al método estático GetDefaultAudioRenderId de la clase MediaDevice . Esto devuelve el identificador del dispositivo de representación de audio predeterminado, que luego se pasa al constructor de AudioDeviceModulesManager para crear una instancia de la clase asociada al dispositivo de audio.
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
Consulta de módulos de dispositivos de audio instalados
Para consultar todos los módulos de dispositivos de audio instalados, llame a FindAll de la clase AudioDeviceModulesManager . Para consultar un conjunto específico de módulos de dispositivo de audio, llame a FindAllById y pase el identificador de los módulos solicitados. En el ejemplo siguiente se define un identificador para un conjunto de módulos, se llama a FindAllById para recuperar una lista de objetos AudioDeviceModule y, a continuación, se imprimen los detalles de cada módulo en la salida de depuración.
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}");
}
Envío de un comando a un módulo de dispositivo de audio y recepción de datos de resultados
Envíe comandos a un módulo de dispositivo de audio llamando a SendCommandAsync en el objeto AudioDeviceModule . El método SendCommandAsync toma una matriz de bytes como argumento. Normalmente, esta matriz de bytes contiene un identificador de comando seguido de los datos asociados al comando, pero el formato de comando y los valores están completamente definidos por el proveedor y se tratan como transparentes por el sistema.
El método SendCommandAsync devuelve una operación asincrónica que, al finalizar, devuelve un objeto ModuleCommandResult que representa el resultado del comando. La propiedad Status contiene un valor de enumeración que indica si el sistema pudo ejecutar el comando. Esto no indica necesariamente que el módulo de dispositivo de audio pudo ejecutar correctamente el comando. La propiedad Result contiene una matriz de bytes que devuelve el módulo de dispositivo de audio para indicar el estado del comando. Normalmente, se trata de un valor que indica que se ha realizado correctamente o no seguido del resultado de los datos del comando. Al igual que con los comandos de módulo, los formatos de respuesta del módulo y los valores se definen por el proveedor.
En el ejemplo siguiente se llama a FindAllAsync para recuperar un conjunto de módulos de dispositivo de audio. DataWriter se usa para crear una matriz de bytes que contiene un comando y datos de ejemplo. Se llama a SendCommandAsync para enviar el búfer de comandos y, una vez completada la operación asincrónica, se devuelve un ModuleCommandResult. Si la ejecución del comando se realizó correctamente, primero se usa dataReader para leer un valor de estado entero devuelto por el módulo. Si este valor es el valor correcto definido por el proveedor, la aplicación lee y usa el resto de los datos de resultados, como para actualizar la interfaz de usuario.
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
}
}
}
}
Recibir notificaciones cuando se modifican los módulos de dispositivo de audio
Las aplicaciones pueden recibir notificaciones cuando se ha actualizado un módulo de dispositivo de audio registrando el evento ModuleNotificationReceived .
C#
var endpointId = MediaDevice.GetDefaultAudioRenderId(AudioDeviceRole.Default);
var audioModuleManager = new AudioDeviceModulesManager(endpointId);
audioModuleManager.ModuleNotificationReceived += AudioModuleManager_ModuleNotificationReceived;
ModuleNotificationReceived se generará cuando se modifique cualquier módulo de dispositivo de audio asociado al dispositivo de audio actual. Para determinar si el evento está asociado a un módulo determinado, obtenga una instancia de AudioDeviceModule mediante el acceso a la propiedad Module de audioDeviceModuleNoticiationEventArgs pasada al controlador de eventos y, a continuación, compruebe la propiedad ClassId que identifica el módulo. Los datos asociados al evento se pasan como una matriz de bytes almacenada en la propiedad NotificationData de los argumentos del evento. Al igual que con los comandos y los resultados, el formato de la matriz de bytes devuelta está definido por el proveedor. En el ejemplo siguiente, si el primer byte de los datos de notificación contiene el valor de ejemplo para la configuración de nivel de reverberación del módulo, los datos se leen y se usan para actualizar la interfaz de usuario.
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];
}
}
}
}