Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo mostra-lhe como usar um MediaFrameReader com MediaCapture para obter dados de áudio de uma fonte de media frame. Para aprender sobre o uso de um MediaFrameReader para obter dados de imagem, como de uma câmara a cores, infravermelhos ou de profundidade, consulte Processar fotogramas de media com o MediaFrameReader. Esse artigo fornece uma visão geral do padrão de utilização do leitor de frames e discute algumas funcionalidades adicionais da classe MediaFrameReader , como o uso do MediaFrameSourceGroup para recuperar frames de múltiplas fontes ao mesmo tempo.
Nota
As funcionalidades discutidas neste artigo só estão disponíveis a partir do Windows 10, versão 1803.
Configurar o seu projeto
O processo de aquisição de frames de áudio é, em grande medida, o mesmo que o de adquirir outros tipos de frames multimédia. Tal como em qualquer aplicação que utilize MediaCapture, deve declarar que a sua aplicação utiliza a capacidade de webcam antes de tentar aceder a qualquer dispositivo com câmara. Se a sua aplicação captar a partir de um dispositivo de áudio, deve também declarar a capacidade do dispositivo de microfone .
Selecionar fontes de quadros e grupos de fontes
O primeiro passo na captura de frames de áudio é inicializar um MediaFrameSource que represente a fonte dos dados de áudio, como um microfone ou outro dispositivo de captura de áudio. Para isso, deve criar uma nova instância do objeto MediaCapture . Neste exemplo, a única definiçã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, pode obter a lista de origens de fotogramas de multimédia acessíveis através da propriedade FrameSources. Este exemplo seleciona todas as origens de fotogramas cujo MediaFrameSourceInfo, que descreve a origem do fotograma, tem um MediaStreamType de Audio, indicando que a origem multimédia produz dados de áudio.
Se a consulta devolver uma ou mais origens de frames, pode verificar a propriedade CurrentFormat para ver se a origem suporta o formato de áudio pretendido - neste exemplo, dados de áudio em vírgula flutuante. Verifique as AudioEncodingProperties para garantir que a codificação de áudio que deseja é suportada pela fonte.
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;
}
Crie e inicie o MediaFrameReader
Obtenha uma nova instância de MediaFrameReader chamando MediaCapture.CreateFrameReaderAsync, passando o objeto MediaFrameSource que selecionou no passo anterior. Por predefinição, as tramas de áudio são obtidas no modo com buffer, o que torna menos provável a sua perda, embora isto ainda possa acontecer se não processar as tramas de áudio com rapidez suficiente e encher o buffer de memória alocado ao sistema.
Registar um handler para o evento MediaFrameReader.FrameArrived , que é ativado pelo sistema quando um novo frame de dados de áudio está disponível. Chame StartAsync para iniciar a aquisição de frames de áudio. Se o leitor de frames não arrancar, o valor de estado devolvido pela chamada terá um valor diferente de Sucesso.
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 processador do evento FrameArrived, chame TryAcquireLatestFrame no objeto MediaFrameReader passado ao processador como remetente para tentar obter uma referência para o fotograma multimédia mais recente. Note que este objeto pode ser nulo, por isso deve sempre verificar antes de usar o objeto. Os tipos de fotogramas multimédia contidos no MediaFrameReference devolvido por TryAcquireLatestFrame dependem do tipo de origem ou origens de fotogramas que configurou para o leitor de fotogramas adquirir. Como o leitor de frames neste exemplo foi configurado para adquirir frames de áudio, ele obtém o frame subjacente usando a propriedade AudioMediaFrame .
Este método auxiliar ProcessAudioFrame no exemplo abaixo mostra como obter uma AudioFrame, que fornece informações como a marca temporal do frame e se este é descontínuo, a partir do objeto AudioMediaFrame. Para ler ou processar os dados da amostra áudio, terá de obter o objeto AudioBuffer do objeto AudioMediaFrame , criar um IMemoryBufferReference e depois chamar o método COM IMemoryBufferByteAccess::GetBuffer para recuperar os dados. Consulte a nota abaixo da lista de códigos para mais informações sobre o acesso a buffers nativos.
O formato dos dados depende da fonte do frame. Neste exemplo, ao selecionar uma fonte de frame media, garantimos explicitamente que a fonte de frame selecionada usava dois canais de dados float. O restante do código de exemplo mostra como determinar a duração e a contagem de amostras para os 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;
}
}
Nota
Para poder operar nos dados de áudio, deve aceder a um buffer de memória nativo. Para isso, deve usar a interface COM IMemoryBufferByteAccess incluindo a lista de códigos abaixo. As operações no buffer nativo devem ser realizadas num método que utilize a palavra-chave insegura . Também tens de assinalar a opção para permitir código inseguro no separador Build do diálogo Project -> Properties.
[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 o uso do MediaFrameReader com dados de áudio
Pode recuperar o AudioDeviceController associado à fonte de frames de áudio acedendo à propriedade MediaFrameSource.Controller . Este objeto pode ser usado para obter ou definir as propriedades do fluxo do dispositivo de captura ou para controlar o nível de captura. O exemplo seguinte silencia o dispositivo de áudio, de modo que os frames continuam a ser adquiridos pelo leitor de frames, mas todas as amostras têm valor de 0.
m_audioDeviceController.Muted = true;
Pode usar um objeto AudioFrame para passar dados de áudio capturados por uma fonte de media frame para um AudioGraph. Passe o frame para o método AddFrame de um AudioFrameInputNode. Para mais informações sobre o uso de gráficos de áudio para capturar, processar e misturar sinais de áudio, consulte Gráficos de áudio.
Tópicos relacionados
Windows developer