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 de trame multimédia. Pour en savoir plus sur l’utilisation d’un MediaFrameReader pour obtenir des données d’image, par exemple à partir d’une caméra de couleur, infrarouge ou de profondeur, consultez Traiter des trames multimédias avec MediaFrameReader. Cet article fournit une vue d’ensemble 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 de plusieurs sources en même temps.

Notes

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

Notes

Il existe un exemple d’application Windows universelle qui illustre l’utilisation de MediaFrameReader pour afficher des images de différentes sources, notamment d’appareils photos couleur, de profondeur et infrarouges. Pour plus d’informations voir Profils d’appareil photo.

Configuration de votre projet

Le processus d’acquisition de trames audio est en grande partie le même que l’acquisition d’autres types de trames multimédias. Comme avec toute application utilisant MediaCapture, vous devez déclarer que votre application utilise la fonctionnalité webcam avant de tenter d’accéder à un appareil photo. Si votre application capture à partir d’un périphérique audio, vous devez également déclarer la fonctionnalité microphone.

Ajouter des fonctionnalités au manifeste de l’application

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

Sélectionnez 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 nouvelle instance de l’objet MediaCapture. Pour cet exemple, le seul paramètre d’initialisation de MediaCapture est la définition de StreamingCaptureMode pour indiquer que nous voulons diffuser de l’audio à partir de l’appareil de capture.

Après avoir appelé MediaCapture.InitializeAsync, vous pouvez obtenir la liste des sources de frame multimédia 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 frame a un MediaStreamType 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 case activée la propriété CurrentFormat pour voir si la source prend en charge le format audio souhaité ( dans cet exemple, float audio data). 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 réduit la probabilité que les images soient supprimées, bien que cela puisse toujours se produire si vous ne traitez pas les images audio assez rapidement et que vous remplissez la mémoire tampon allouée du système.

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

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 passé en tant qu’expéditeur au gestionnaire pour tenter de récupérer une référence à la dernière image multimédia. Notez que cet objet peut être null. Vous devez donc toujours case activée avant d’utiliser l’objet . Les fautes de frappe de l’image multimédia encapsulée dans mediaFrameReference retournées par TryAcquireLatestFrame dépendent du type de source de trame ou de sources que vous avez configurées pour acquérir le lecteur d’images. Étant donné que le lecteur d’images dans cet exemple a été configuré pour acquérir des trames 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 discontinu à 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 un 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 du frame. Dans cet exemple, lors de la sélection d’une source de trame multimédia, nous nous sommes explicitement assurés que la source de trame sélectionnée utilisait un canal unique 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 le frame.

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;

    }
}

Notes

Pour pouvoir utiliser les données audio, vous devez accéder à une mémoire tampon native. Pour ce faire, vous devez utiliser l’interface COM IMemoryBufferByteAccess en incluant la liste de code ci-dessous. Les opérations sur la mémoire tampon native doivent être effectuées dans une méthode qui utilise le mot clé non sécurisé. Vous devez également case activée la zone pour autoriser le code non sécurisé dans l’onglet Générer 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 d’images 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 désactive 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 passer des données audio capturées par une source de trame multimédia dans un audiograph. Passez le frame dans 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.