Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo mostra como usar um MediaFrameReader com MediaCapture para obter dados de áudio de uma fonte de quadro de mídia. Para saber mais sobre o uso de um MediaFrameReader para obter dados de imagem, por exemplo, de uma câmera colorida, infravermelha ou de profundidade, consulte Processar quadros de mídia com MediaFrameReader. Esse artigo fornece uma visão geral do padrão de uso do leitor de quadros e discute alguns recursos adicionais da classe MediaFrameReader , como usar MediaFrameSourceGroup para recuperar quadros de várias fontes ao mesmo tempo.
Note
Os recursos discutidos neste artigo só estão disponíveis a partir do Windows 10, versão 1803.
Configurando seu projeto
O processo de aquisição de quadros de áudio é praticamente o mesmo que adquirir outros tipos de quadros de mídia. Assim como acontece com qualquer aplicativo que use o MediaCapture, você deve declarar que seu aplicativo usa a funcionalidade de webcam antes de tentar acessar qualquer dispositivo de câmera. Se o seu aplicativo capturar áudio de um dispositivo de áudio, você também deverá declarar a capacidade de dispositivo microfone.
Selecionar fontes de quadros e grupos de fontes de quadros
A primeira etapa na captura de quadros de áudio é inicializar um MediaFrameSource que representa a origem dos dados de áudio, como um microfone ou outro dispositivo de captura de áudio. Para fazer isso, você deve criar uma nova instância do objeto MediaCapture . Para este exemplo, a única configuração de inicialização para o MediaCapture é definir o StreamingCaptureMode para indicar que queremos transmitir áudio do dispositivo de captura.
Depois de chamar MediaCapture.InitializeAsync, você pode obter a lista de fontes de quadro de mídia acessíveis com a propriedade FrameSources . Esse exemplo seleciona todas as fontes de quadro em que MediaFrameSourceInfo que descreve a fonte de quadro tem MediaStreamTypeÁudio, indicando que a fonte de mídia produz dados de áudio.
Se a consulta retornar uma ou mais fontes de quadros, você poderá verificar a propriedade CurrentFormat para ver se a fonte oferece suporte ao formato de áudio desejado, neste exemplo, dados de áudio em ponto flutuante. Verifique as AudioEncodingProperties para verificar se a codificação de áudio desejada tem suporte na origem.
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;
}
Criar e iniciar o MediaFrameReader
Obtenha uma nova instância do MediaFrameReader chamando MediaCapture.CreateFrameReaderAsync, passando o objeto MediaFrameSource selecionado na etapa anterior. Por padrão, os quadros de áudio são obtidos no modo com buffer, o que torna menos provável que os quadros sejam descartados, embora isso ainda possa ocorrer se você não estiver processando os quadros de áudio com rapidez suficiente e encher o buffer de memória alocado do sistema.
Registre um manipulador para o evento MediaFrameReader.FrameArrived , que é gerado pelo sistema quando um novo quadro de dados de áudio está disponível. Chame StartAsync para iniciar a aquisição de quadros de áudio. Se o leitor de quadros falhar ao iniciar, o valor de status retornado pela chamada será diferente de Success.
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.");
}
No manipulador de eventos FrameArrived , chame TryAcquireLatestFrame no objeto MediaFrameReader passado como o remetente para o manipulador para tentar recuperar uma referência ao quadro de mídia mais recente. Observe que esse objeto pode ser nulo, portanto, você sempre deve verificar antes de usar o objeto. Os tipos de quadro de mídia contidos em MediaFrameReference retornado por TryAcquireLatestFrame dependem do tipo de fonte de quadro ou fontes de quadro que você configurou para o leitor de quadros que serão adquiridos. Como o leitor de quadros neste exemplo foi configurado para adquirir quadros de áudio, ele obtém o quadro subjacente usando a propriedade AudioMediaFrame .
Esse método auxiliar ProcessAudioFrame, no exemplo a seguir, mostra como obter um AudioFrame, que fornece informações sobre o carimbo de data e hora do quadro e se ele é descontínuo, direto do objeto AudioMediaFrame. Para ler ou processar os dados de exemplo de áudio, você precisará obter o objeto AudioBuffer do objeto AudioMediaFrame , criar um IMemoryBufferReference e, em seguida, chamar o método COM IMemoryBufferByteAccess::GetBuffer para recuperar os dados. Consulte a observação abaixo da listagem de código para obter mais informações sobre como acessar buffers nativos.
O formato dos dados depende da origem do quadro. Neste exemplo, ao selecionar uma fonte de quadro de mídia, garantimos explicitamente que a fonte de quadro selecionada usou dois canais de dados flutuantes. O restante do código de exemplo mostra como determinar a duração e o número de amostras dos dados de áudio no 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;
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;
}
}
Note
Para operar nos dados de áudio, você deve acessar um buffer de memória nativo. Para fazer isso, você deve usar a interface COM IMemoryBufferByteAccess , incluindo a listagem de código abaixo. As operações no buffer nativo devem ser executadas em um método que usa a palavra-chave não segura . Você também precisa marcar a caixa de seleção para permitir código inseguro na guia Compilar da caixa de diálogo Projeto -> Propriedades.
[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
void GetBuffer(out byte* buffer, out uint capacity);
}
Informações adicionais sobre como usar MediaFrameReader com dados de áudio
Você pode recuperar o AudioDeviceController associado à origem do quadro de áudio acessando a propriedade MediaFrameSource.Controller . Esse objeto pode ser usado para obter ou definir as propriedades de fluxo do dispositivo de captura ou para controlar o nível de captura. O exemplo a seguir silencia o dispositivo de áudio para que os quadros continuem a ser adquiridos pelo leitor de quadros, mas todos os exemplos têm o valor 0.
m_audioDeviceController.Muted = true;
Você pode usar um objeto AudioFrame para passar dados de áudio capturados por uma fonte de quadro de mídia para um AudioGraph. Passe o quadro para o método AddFrame de um AudioFrameInputNode. Para obter mais informações sobre como usar grafos de áudio para capturar, processar e misturar sinais de áudio, consulte grafos de áudio.
Tópicos relacionados:
Windows developer