Aracılığıyla paylaş


MediaFrameReader ile ses çerçevelerini işleme

Bu makalede, bir medya çerçevesi kaynağından ses verileri almak için MediaCapture ile MediaFrameReader nasıl kullanılacağı gösterilmektedir. Renk, kızılötesi veya derinlik kamerası gibi görüntü verilerini almak için MediaFrameReader kullanma hakkında bilgi edinmek için bkz. MediaFrameReaderile medya çerçevelerini işleme . Bu makalede çerçeve okuyucu kullanım düzenine genel bir genel bakış sağlanır ve MediaFrameReader sınıfının, aynı anda birden çok kaynaktan çerçeve almak için MediaFrameSourceGroup kullanma gibi bazı ek özellikleri ele alınmaktadır.

Not

Bu makalede açıklanan özellikler yalnızca Windows 10, sürüm 1803'den itibaren kullanılabilir.

Projenizi ayarlama

Ses çerçeveleri alma işlemi büyük ölçüde diğer medya karesi türlerini almakla aynıdır. MediaCapturekullanan herhangi bir uygulamada olduğu gibi, herhangi bir kamera cihazına erişmeye çalışmadan önce uygulamanızın web kamerası özelliğini kullandığını bildirmeniz gerekir. Uygulamanız bir ses cihazından yakalayacaksa, mikrofon cihaz özelliğini bildirmeniz gerekir.

Çerçeve kaynaklarını ve çerçeve kaynak gruplarını seçme

Ses çerçevelerini yakalamanın ilk adımı, mikrofon veya başka bir ses yakalama cihazı gibi ses verilerinin kaynağını temsil eden bir MediaFrameSource başlatmaktır. Bunu yapmak için MediaCapture nesnesinin yeni bir örneğini oluşturmanız gerekir. Bu örnekte MediaCapture için tek başlatma ayarı, yakalama cihazından ses akışı yapmak istediğimizi belirtmek için StreamingCaptureMode ayarlamaktır.

MediaCapture.InitializeAsyncçağrıldıktan sonra, FrameSources özelliğiyle erişilebilir medya çerçevesi kaynaklarının listesini alabilirsiniz. Bu örnek, çerçeve kaynağını açıklayan MediaFrameSourceInfo, ses verileri ürettiğini belirten Sestipinde bir MediaStreamType içeriyorsa, tüm bu çerçeve kaynaklarını seçer.

Sorgu bir veya daha fazla çerçeve kaynağı döndürüyorsa, kaynağın istediğiniz ses biçimini desteklenip desteklemediğini görmek için CurrentFormat özelliğini de kontrol edebilirsiniz. Bu örnekte ses verilerini kaydırabilirsiniz. İstediğiniz ses kodlamasının kaynak tarafından desteklendiğinden emin olmak için AudioEncodingProperties denetleyin.

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

var audioFrameSources = m_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 != 2
    || format.AudioEncodingProperties.SampleRate != 48000)
{
    return;
}

MediaFrameReader Oluşturma ve Başlatma

Önceki adımda seçtiğiniz MediaFrameSource nesnesini geçirerek MediaCapture.CreateFrameReaderAsyncçağırarak yeni bir MediaFrameReader örneği alın. Varsayılan olarak, ses çerçeveleri arabelleğe alınmış modda elde edilir, bu da çerçevelerin düşürülme olasılığını azaltır. Ancak, ses çerçevelerini yeterince hızlı işlemezseniz ve sistemin ayrılan bellek arabelleğini doldurursanız bu durum yine de meydana gelebilir.

Yeni bir ses verisi çerçevesi mevcut olduğunda sistem tarafından tetiklenen MediaFrameReader.FrameArrived olayı için bir işleyici kaydedin. Ses çerçevelerinin edinimine başlamak için StartAsync çağırın. Çerçeve okuyucu başlatılamazsa, çağrıdan döndürülen durum değeri Successdışında bir değere sahip olur.

m_mediaFrameReader = await m_mediaCapture.CreateFrameReaderAsync(frameSource);

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

m_mediaFrameReader.FrameArrived += MediaFrameReader_AudioFrameArrived;

var status = await m_mediaFrameReader.StartAsync();

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

`FrameArrived olay işleyicisinde, en son medya çerçevesine ulaşmak için gönderici olarak işleyiciye geçirilen MediaFrameReader nesnesi üzerinde TryAcquireLatestFrame çağrısı yapın.` Bu nesnenin null olabileceğini unutmayın, bu nedenle nesneyi kullanmadan önce her zaman denetlemeniz gerekir. TryAcquireLatestFrame tarafından döndürülen MediaFrameReference içindeki medya çerçevesinin türleri, çerçeve okuyucuyu elde etmek için yapılandırdığınız çerçeve kaynağının veya kaynaklarının türüne bağlıdır. Bu örnekte çerçeve okuyucu ses çerçeveleri almak üzere ayarlandığı için, temel çerçeveyi AudioMediaFrame özelliği aracılığıyla alır.

Aşağıdaki örnekteki bu ProcessAudioFrame yardımcı yöntemi, çerçevenin zaman damgası ve AudioMediaFrame nesnesinden kesintili olup olmadığı gibi bilgiler sağlayan bir AudioFrame nasıl elde edilebildiğini gösterir. Ses örneği verilerini okumak veya işlemek için, AudioMediaFrame nesnesinden AudioBuffer nesnesini almanız,bir IMemoryBufferReference oluşturmanız ve ardından verileri almak için IMemoryBufferByteAccess::GetBuffer COM yöntemini çağırmanız gerekir. Yerel arabelleklere erişim hakkında daha fazla bilgi için kod listesinin altındaki notu inceleyin.

Verilerin biçimi çerçeve kaynağına bağlıdır. Bu örnekte, bir medya çerçevesi kaynağı seçerken, seçilen çerçeve kaynağının iki kayan veri kanalı kullandığından açıkça emin olduk. Örnek kodun geri kalanında, çerçevedeki ses verileri için süre ve örnek sayısının nasıl belirleneceği gösterilir.

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;

        var memoryBuffer = reference.As<IMemoryBufferByteAccess>();
        memoryBuffer.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;

    }
}

Not

Ses verileri üzerinde çalışmak için yerel bir bellek arabelleğine erişmeniz gerekir. Bunu yapmak için, aşağıdaki kod listesini ekleyerek IMemoryBufferByteAccess COM arabirimini kullanmanız gerekir. Yerel arabellekteki işlemler, güvenli olmayan anahtar sözcüğünü kullanan bir yöntemde gerçekleştirilmelidir. Ayrıca, Projesi -> Özellikler iletişim kutusunun Derleme sekmesinde güvenli olmayan koda izin vermek için kutuyu işaretlemeniz gerekir.

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

MediaFrameReader'i ses verileriyle kullanma hakkında ek bilgi

Ses çerçevesi kaynağıyla ilişkili AudioDeviceController'ü, MediaFrameSource.Controller özelliğine erişerek alabilirsiniz. Bu nesne, yakalama cihazının akış özelliklerini almak veya ayarlamak ya da yakalama düzeyini denetlemek için kullanılabilir. Aşağıdaki örnek, çerçevelerin çerçeve okuyucu tarafından alınmaya devam etmesi için ses cihazını kapatır, ancak tüm örneklerin değeri 0'dır.

m_audioDeviceController.Muted = true;

AudioFrame nesnesini kullanarak, bir medya çerçevesi kaynağı tarafından elde edilen ses verilerini bir AudioGraph'e aktarabilirsiniz. Çerçeveyi bir AudioFrameInputNodeAddFrame yöntemine geçirin. Ses sinyallerini yakalamak, işlemek ve karıştırmak için ses graflarını kullanma hakkında daha fazla bilgi için bkz. Ses grafikleri.