Freigeben über


Verarbeiten von Audioframes mit „MediaFrameReader“

In diesem Artikel wird gezeigt, wie Sie einen MediaFrameReader mit MediaCapture verwenden, um Audiodaten aus einer Medienframequelle abzurufen. Informationen zur Verwendung eines MediaFrameReader zum Abrufen von Bilddaten, z. B. aus einer Farbe, Infrarot- oder Tiefenkamera, finden Sie unter Verarbeiten von Medienframes mit MediaFrameReader. Dieser Artikel enthält eine allgemeine Übersicht über das Verwendungsmuster des Framelesers und erläutert einige zusätzliche Features der MediaFrameReader-Klasse , z. B. die Verwendung von MediaFrameSourceGroup zum gleichzeitigen Abrufen von Frames aus mehreren Quellen.

Hinweis

Die in diesem Artikel beschriebenen Features sind nur ab Windows 10, Version 1803, verfügbar.

Hinweis

Es gibt ein Beispiel für universelle Windows-Apps, das die Verwendung von MediaFrameReader zum Anzeigen von Frames aus verschiedenen Framequellen veranschaulicht, einschließlich Farb-, Tiefen- und Infrarotkameras. Weitere Informationen finden Sie im Beispiel für Kameraframes.

Einrichten Ihres Projekts

Der Prozess zum Abrufen von Audioframes ist weitgehend identisch mit dem Abrufen anderer Medienframetypen. Wie bei jeder App, die MediaCapture verwendet, müssen Sie deklarieren, dass Ihre App die Webcamfunktion verwendet, bevor Sie versuchen, auf ein Kameragerät zuzugreifen. Wenn Ihre App von einem Audiogerät erfasst wird, sollten Sie auch die Mikrofongerätefunktion deklarieren.

Hinzufügen von Funktionen zum App-Manifest

  1. Öffnen Sie in Microsoft Visual Studio im Projektmappen-Explorer, den Designer für das Anwendungsmanifest, indem Sie auf das Element package.appxmanifest doppelklicken.
  2. Wählen Sie die Registerkarte Funktionen aus.
  3. Aktivieren Sie das Kästchen für Webcam und das Kästchen für Mikrofon.
  4. Für den Zugriff auf die Bilder- und Videobibliothek markieren Sie die Kästchen für Bilderbibliothek und das Kästchen für Videobibliothek.

Auswählen von Framequellen und Framequellgruppen

Der erste Schritt bei der Aufnahme von Audioframes besteht darin, eine MediaFrameSource zu initialisieren, die die Quelle der Audiodaten darstellt, z. B. ein Mikrofon oder ein anderes Audioaufnahmegerät. Dazu müssen Sie eine neue Instanz des MediaCapture-Objekts erstellen. In diesem Beispiel legt die einzige Initialisierungseinstellung für MediaCapture den StreamingCaptureMode fest, um anzugeben, dass wir Audio vom Aufnahmegerät streamen möchten.

Nach dem Aufrufen von MediaCapture.InitializeAsync können Sie die Liste der barrierefreien Medienframequellen mit der FrameSources-Eigenschaft abrufen. In diesem Beispiel wird eine Linq-Abfrage verwendet, um alle Framequellen auszuwählen, in denen die MediaFrameSourceInfo, die die Framequelle beschreibt, einen MediaStreamType von Audio aufweist, der angibt, dass die Medienquelle Audiodaten erzeugt.

Wenn die Abfrage eine oder mehrere Framequellen zurückgibt, können Sie die CurrentFormat-Eigenschaft überprüfen, um festzustellen, ob die Quelle das gewünschte Audioformat unterstützt – in diesem Beispiel float-Audiodaten. Überprüfen Sie die AudioEncodingProperties , um sicherzustellen, dass die gewünschte Audiocodierung von der Quelle unterstützt wird.

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

Erstellen und Starten des MediaFrameReader

Rufen Sie eine neue Instanz von MediaFrameReader ab, indem Sie MediaCapture.CreateFrameReaderAsync aufrufen und das MediaFrameSource-Objekt übergeben, das Sie im vorherigen Schritt ausgewählt haben. Standardmäßig werden Audioframes im gepufferten Modus abgerufen, sodass es weniger wahrscheinlich ist, dass Frames gelöscht werden, obwohl dies weiterhin auftreten kann, wenn Sie Audioframes nicht schnell genug verarbeiten und den bestimmten Speicherpuffer des Systems ausfüllen.

Registrieren Sie einen Handler für das MediaFrameReader.FrameArrived-Ereignis , das vom System ausgelöst wird, wenn ein neuer Frame von Audiodaten verfügbar ist. Rufen Sie StartAsync auf, um mit dem Erwerb von Audioframes zu beginnen. Wenn der Framereader nicht gestartet werden kann, weist der vom Aufruf zurückgegebene Statuswert einen anderen Wert als Success auf.

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

Rufen Sie im FrameArrived-Ereignishandler TryAcquireLatestFrame für das MediaFrameReader-Objekt auf, das als Absender an den Handler übergeben wird, um zu versuchen, einen Verweis auf den neuesten Medienframe abzurufen. Beachten Sie, dass dieses Objekt null sein kann, daher sollten Sie immer überprüfen, bevor Sie das Objekt verwenden. Die Von TryAcquireLatestFrame zurückgegebenen Typs von MediaFrameReference hängen vom Typ der Framequelle oder -quellen ab, die Sie für den Framereader konfiguriert haben. Da der Frameleser in diesem Beispiel zum Abrufen von Audioframes eingerichtet wurde, ruft er den zugrunde liegenden Frame mithilfe der AudioMediaFrame-Eigenschaft ab.

Diese ProcessAudioFrame-Hilfsmethode im folgenden Beispiel zeigt, wie Sie einen AudioFrame abrufen, der Informationen wie den Zeitstempel des Frames bereitstellt und ob es vom AudioMediaFrame-Objekt nicht zusammenhängend ist. Zum Lesen oder Verarbeiten der Audiobeispieldaten müssen Sie das AudioBuffer-Objekt aus dem AudioMediaFrame-Objekt abrufen, eine IMemoryBufferReference erstellen und dann die COM-Methode IMemoryBufferByteAccess::GetBuffer aufrufen, um die Daten abzurufen. Weitere Informationen zum Zugreifen auf systemeigene Puffer finden Sie in der Codeauflistung unten.

Das Format der Daten hängt von der Framequelle ab. In diesem Beispiel wurde beim Auswählen einer Medienframequelle explizit sichergestellt, dass die ausgewählte Framequelle einen einzelnen Kanal mit Float-Daten verwendet hat. Im restlichen Beispielcode wird gezeigt, wie die Dauer und die Beispielanzahl für die Audiodaten im Frame bestimmt werden.

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;

    }
}

Hinweis

Um die Audiodaten zu verwenden, müssen Sie auf einen systemeigenen Speicherpuffer zugreifen. Dazu müssen Sie die COM-Schnittstelle "IMemoryBufferByteAccess " verwenden, indem Sie die nachstehende Codeauflistung einschließen. Vorgänge im systemeigenen Puffer müssen in einer Methode ausgeführt werden, die das unsichere Schlüsselwort verwendet. Außerdem müssen Sie das Kontrollkästchen aktivieren, um unsicheren Code auf der Registerkarte "Erstellen " im Dialogfeld "Projekt> - Eigenschaften " zuzulassen.

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

Weitere Informationen zur Verwendung von MediaFrameReader mit Audiodaten

Sie können den audioDeviceController abrufen, der der Audioframequelle zugeordnet ist, indem Sie auf die MediaFrameSource.Controller-Eigenschaft zugreifen. Dieses Objekt kann zum Abrufen oder Festlegen der Datenstromeigenschaften des Aufnahmegeräts oder zum Steuern der Aufnahmeebene verwendet werden. Im folgenden Beispiel wird das Audiogerät stummgeschaltet, sodass Frames weiterhin vom Frameleser abgerufen werden, aber alle Beispiele haben den Wert 0.

audioDeviceController.Muted = true;

Sie können ein AudioFrame-Objekt verwenden, um Audiodaten, die von einer Medienframequelle erfasst werden, an ein AudioGraph zu übergeben. Übergeben Sie den Frame an die AddFrame-Methode eines AudioFrameInputNode. Weitere Informationen zur Verwendung von Audiodiagrammen zum Erfassen, Verarbeiten und Mischen von Audiosignalen finden Sie unter Audiodiagramme.