Traiter des trames audio avec MediaFrameReader

Cet article vous montre comment utiliser un MediaFrameReader avec MediaCapture pour obtenir des données audio à partir d’une source d’images multimédias. Pour en savoir plus sur l’utilisation d’un MediaFrameReader pour obtenir des données d’image, comme à partir d’une caméra de couleur, infrarouge ou de profondeur, consultez Traiter les images multimédias avec MediaFrameReader. Cet article fournit une vue d’ensemble générale du modèle d’utilisation du lecteur d’images et décrit certaines fonctionnalités supplémentaires de la classe MediaFrameReader , telles que l’utilisation de MediaFrameSourceGroup pour récupérer des images à partir de plusieurs sources en même temps.

Remarque

Les fonctionnalités décrites dans cet article sont disponibles uniquement à partir de Windows 10, version 1803.

Remarque

Il existe un exemple d’application Windows universelle qui illustre l’utilisation de MediaFrameReader pour afficher des images provenant de différentes sources d’images, notamment des caméras couleur, profondeur et infrarouge. Pour plus d’informations, consultez l’exemple d’images caméra.

Configuration de votre projet

Le processus d’acquisition d’images audio est largement identique à l’acquisition d’autres types de trames multimédias. Comme pour toute application qui utilise MediaCapture, vous devez déclarer que votre application utilise la fonctionnalité webcam avant de tenter d’accéder à n’importe quel appareil photo. Si votre application capture à partir d’un appareil audio, vous devez également déclarer la fonctionnalité d’appareil microphone .

Ajouter des fonctionnalités au manifeste de l’application

  1. Dans Microsoft Visual Studio, dans Explorateur de solutions, ouvrez le concepteur du manifeste de l’application en double-cliquant sur l’élément package.appxmanifest.
  2. Sélectionnez l’onglet Fonctionnalités.
  3. Cochez la case Webcam et la case Microphone.
  4. Pour l’accès à la bibliothèque d’images et de vidéos, cochez les cases Bibliothèque d’images et Bibliothèque de vidéos.

Sélectionner des sources d’images et des groupes de sources d’images

La première étape de la capture d’images audio consiste à initialiser un MediaFrameSource représentant la source des données audio, comme un microphone ou un autre périphérique de capture audio. Pour ce faire, vous devez créer une instance de l’objet MediaCapture . Pour cet exemple, le seul paramètre d’initialisation pour MediaCapture définit le StreamingCaptureMode pour indiquer que nous voulons diffuser du contenu audio à partir de l’appareil de capture.

Après avoir appelé MediaCapture.InitializeAsync, vous pouvez obtenir la liste des sources d’images multimédias accessibles avec la propriété FrameSources. Cet exemple utilise une requête Linq pour sélectionner toutes les sources d’images où MediaFrameSourceInfo décrivant la source de trame a un MediaStreamType d’audio, indiquant que la source multimédia produit des données audio.

Si la requête retourne une ou plusieurs sources d’images, vous pouvez vérifier la propriété CurrentFormat pour voir si la source prend en charge le format audio souhaité , dans cet exemple, les données audio float. Vérifiez audioEncodingProperties pour vous assurer que l’encodage audio souhaité est pris en charge par la source.

mediaCapture = new MediaCapture();
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings()
{
    StreamingCaptureMode = StreamingCaptureMode.Audio,
};
await mediaCapture.InitializeAsync(settings);

var audioFrameSources = mediaCapture.FrameSources.Where(x => x.Value.Info.MediaStreamType == MediaStreamType.Audio);

if (audioFrameSources.Count() == 0)
{
    Debug.WriteLine("No audio frame source was found.");
    return;
}

MediaFrameSource frameSource = audioFrameSources.FirstOrDefault().Value;

MediaFrameFormat format = frameSource.CurrentFormat;
if (format.Subtype != MediaEncodingSubtypes.Float)
{
    return;
}

if (format.AudioEncodingProperties.ChannelCount != 1
    || format.AudioEncodingProperties.SampleRate != 48000)
{
    return;
}

Créer et démarrer MediaFrameReader

Obtenez une nouvelle instance de MediaFrameReader en appelant MediaCapture.CreateFrameReaderAsync, en passant l’objet MediaFrameSource que vous avez sélectionné à l’étape précédente. Par défaut, les images audio sont obtenues en mode mis en mémoire tampon, ce qui rend moins probable que les images seront supprimées, bien que cela puisse toujours se produire si vous ne traitez pas suffisamment rapidement les images audio et remplissez la mémoire tampon allotée du système.

Inscrivez un gestionnaire pour l’événement MediaFrameReader.FrameArrived, déclenché par le système lorsqu’une nouvelle trame de données audio est disponible. Appelez StartAsync pour commencer l’acquisition d’images audio. Si le lecteur d’images ne parvient pas à démarrer, la valeur d’état retournée par l’appel a une valeur autre que Success.

mediaFrameReader = await mediaCapture.CreateFrameReaderAsync(frameSource);

// Optionally set acquisition mode. Buffered is the default mode for audio.
mediaFrameReader.AcquisitionMode = MediaFrameReaderAcquisitionMode.Buffered;

mediaFrameReader.FrameArrived += MediaFrameReader_AudioFrameArrived;

var status = await mediaFrameReader.StartAsync();

if (status != MediaFrameReaderStartStatus.Success)
{
    Debug.WriteLine("The MediaFrameReader couldn't start.");
}

Dans le gestionnaire d’événements FrameArrived, appelez TryAcquireLatestFrame sur l’objet MediaFrameReader transmis en tant qu’expéditeur au gestionnaire pour tenter de récupérer une référence à la dernière trame multimédia. Notez que cet objet peut être null. Vous devez donc toujours vérifier avant d’utiliser l’objet. Les fautes de frappe du frame multimédia encapsulées dans MediaFrameReference retournées par TryAcquireLatestFrame dépendent du type de source ou de sources de trame que vous avez configuré le lecteur d’images à acquérir. Étant donné que le lecteur d’images de cet exemple a été configuré pour acquérir des images audio, il obtient l’image sous-jacente à l’aide de la propriété AudioMediaFrame.

Cette méthode d’assistance ProcessAudioFrame dans l’exemple ci-dessous montre comment obtenir un AudioFrame qui fournit des informations telles que l’horodatage de l’image et s’il est interrompu à partir de l’objet AudioMediaFrame. Pour lire ou traiter les exemples de données audio, vous devez obtenir l’objet AudioBuffer à partir de l’objet AudioMediaFrame, créer une IMemoryBufferReference, puis appeler la méthode COM IMemoryBufferByteAccess ::GetBuffer pour récupérer les données. Pour plus d’informations sur l’accès aux mémoires tampons natives, consultez la note ci-dessous.

Le format des données dépend de la source de trame. Dans cet exemple, lors de la sélection d’une source de trame multimédia, nous avons explicitement fait en sorte que la source d’images sélectionnée utilise un seul canal de données float. Le reste de l’exemple de code montre comment déterminer la durée et le nombre d’échantillons pour les données audio dans l’image.

private void MediaFrameReader_AudioFrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
    using (MediaFrameReference reference = sender.TryAcquireLatestFrame())
    {
        if (reference != null)
        {
            ProcessAudioFrame(reference.AudioMediaFrame);
        }
    }
}
unsafe private void ProcessAudioFrame(AudioMediaFrame audioMediaFrame)
{

    using (AudioFrame audioFrame = audioMediaFrame.GetAudioFrame())
    using (AudioBuffer buffer = audioFrame.LockBuffer(AudioBufferAccessMode.Read))
    using (IMemoryBufferReference reference = buffer.CreateReference())
    {
        byte* dataInBytes;
        uint capacityInBytes;
        float* dataInFloat;


        ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacityInBytes);
        
        // The requested format was float
        dataInFloat = (float*)dataInBytes;

        // Get the number of samples by multiplying the duration by sampling rate: 
        // duration [s] x sampling rate [samples/s] = # samples 

        // Duration can be gotten off the frame reference OR the audioFrame
        TimeSpan duration = audioMediaFrame.FrameReference.Duration;

        // frameDurMs is in milliseconds, while SampleRate is given per second.
        uint frameDurMs = (uint)duration.TotalMilliseconds;
        uint sampleRate = audioMediaFrame.AudioEncodingProperties.SampleRate;
        uint sampleCount = (frameDurMs * sampleRate) / 1000;

    }
}

Remarque

Pour effectuer des opérations sur les données audio, vous devez accéder à une mémoire tampon de mémoire native. Pour ce faire, vous devez utiliser l’interface COM IMemoryBufferByteAccess en incluant la liste de codes ci-dessous. Les opérations sur la mémoire tampon native doivent être effectuées dans une méthode qui utilise le mot clé unsafe . Vous devez également cocher la case pour autoriser le code non sécurisé dans l’onglet Build de la boîte de dialogue Projet -> Propriétés .

[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
    void GetBuffer(out byte* buffer, out uint capacity);
}

Informations supplémentaires sur l’utilisation de MediaFrameReader avec des données audio

Vous pouvez récupérer l’AudioDeviceController associé à la source de trame audio en accédant à la propriété MediaFrameSource.Controller. Cet objet peut être utilisé pour obtenir ou définir les propriétés de flux de l’appareil de capture ou pour contrôler le niveau de capture. L’exemple suivant montre comment désactiver le périphérique audio afin que les images continuent d’être acquises par le lecteur d’images, mais tous les exemples ont la valeur 0.

audioDeviceController.Muted = true;

Vous pouvez utiliser un objet AudioFrame pour transmettre des données audio capturées par une source de trame multimédia dans un AudioGraph. Transmettez le frame à la méthode AddFrame d’un AudioFrameInputNode. Pour plus d’informations sur l’utilisation de graphiques audio pour capturer, traiter et mélanger des signaux audio, consultez graphiques audio.