public void EnviarAmostra(ref ICarenBuffer Param_Buffer, uint Param_CountAudioBytes) { //Sincroniza o acesso a lista que contém os buffers de áudio. lock (SyncList) { //Novo buffer a ser adicionado. ICarenBuffer NewBuffer = new CarenBuffer(); //Cria o buffer com a quantidade de dados validos. NewBuffer.CreateBuffer(Param_CountAudioBytes); //Cópia os dados do buffer do dispositivo de áudio para a amostra atual. NewBuffer.Write(Param_Buffer, 0, Param_CountAudioBytes); //Reseta a posição do buffer. NewBuffer.SetPosition(0); //Define as informações. NewBuffer.TamanhoValido = Param_CountAudioBytes; NewBuffer.Tamanho = Param_CountAudioBytes; //Adiciona na lista. ListaBuffersAudio.Add(NewBuffer); } }
/// <summary> /// Método responsável por criar e preparar o arquivo que vai receber os dados capturados do dispositivo de áudio. /// </summary> /// <param name="Param_Url">A url para o arquivo que será criado.</param> /// <returns></returns> public CarenResult CriarArquivoWav(String Param_Url) { //Variavel que vai retornar o resultado. CarenResult Resultado = new CarenResult(ResultCode.ER_FAIL, false); //Variaveis ICarenBuffer BufferHeaderZero = null; ulong RefTotalWritten = 0; //Deleta o arquivo se ja existir. File.Delete(Param_Url); //Chama o construtor para criar o arquivo de destino. myCaptureAudio.StreamFile = new CarenStream(Param_Url, CA_STGMs.CA_STGM_READWRITE, CA_FILE_ATTRIBUTES.CA_FILE_ATTRIBUTE_NORMAL, true); //Verifica se não houve erro. if (myCaptureAudio.StreamFile is null) { //Define erro na operação. Resultado.AdicionarCodigo(ResultCode.ER_FAIL, false); //Sai do método. goto Done; } //Cria um buffer que vai conter o tamanho do HEADER do arquivo Wav, mais preenchidos com zero. BufferHeaderZero = new CarenBuffer(); BufferHeaderZero.CreateBuffer(MyHeaderInfoFile.HeaderSize); //Preenche o buffer com Zeros. BufferHeaderZero.FillBuffer(); //Escreve o tamanho do header no inicio do fluxo para poder reservar. Resultado = myCaptureAudio.StreamFile.Write(BufferHeaderZero, MyHeaderInfoFile.HeaderSize, ref RefTotalWritten); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao escrever o HEADER vazio no inicio do fluxo. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Define sucesso na operação Resultado.AdicionarCodigo(ResultCode.SS_OK, true); Done :; //Retorna return(Resultado); }
/// <summary> /// Método responsável por terminar de configurar o header e finalizar o arquivo. /// </summary> /// <returns></returns> public CarenResult FinalizarArquivoWav() { //Variavel que vai retornar o resultado. CarenResult Resultado = new CarenResult(ResultCode.ER_FAIL, false); //Variaveis a serem utilizadas. ulong OutTotalWriter = 0; //Cria o buffer que vai conter os dados a serem escritos. ICarenBuffer BufferWriter = new CarenBuffer(); //Cria o buffer para escrever os dados do header. BufferWriter.CreateBuffer(MyHeaderInfoFile.HeaderSize); //Calcula o tamanho total do arquivo. MyHeaderInfoFile.TotalFileSize = (uint)MyHeaderInfoFile.TotalLenghtCaptured + MyHeaderInfoFile.HeaderSize; //Escreve os dados do header. BufferWriter.Write(MFTFuncs._FCC("RIFF")); BufferWriter.Write(MyHeaderInfoFile.TotalFileSize); BufferWriter.Write(MFTFuncs._FCC("WAVE")); BufferWriter.Write(MFTFuncs._FCC("fmt ")); BufferWriter.Write(MyHeaderInfoFile.SubChunkSize); BufferWriter.Write(MyHeaderInfoFile.FormatAudioData); //Formato dos dados = IEEE Float. BufferWriter.Write(MyHeaderInfoFile.Canais); //Quantidade de canais. BufferWriter.Write(MyHeaderInfoFile.SampleRate); //Sample Rate. BufferWriter.Write((uint)MyHeaderInfoFile.BitsPerSample * MyHeaderInfoFile.Canais * MyHeaderInfoFile.SampleRate / 8); //Bytes per sample. BufferWriter.Write((ushort)(MyHeaderInfoFile.BitsPerSample * MyHeaderInfoFile.Canais / 8)); //Alinhamento de bloco. BufferWriter.Write(MyHeaderInfoFile.BitsPerSample); //Bitpersample BufferWriter.Write(MFTFuncs._FCC("data")); //Marca inicio do buffer. BufferWriter.Write((uint)MyHeaderInfoFile.TotalLenghtCaptured); //Tamanho total dos dados de audio. //Define como posicação zero no fluxo. Resultado = myCaptureAudio.StreamFile.Seek(0, CA_STREAM_SEEK.CA_STREAM_SEEK_SET, out ulong NewSeekPos); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar definir uma posição no fluxo para escrita do header. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Chama o método para escrever os dados no fluxo. Resultado = myCaptureAudio.StreamFile.Write(BufferWriter, MyHeaderInfoFile.HeaderSize, ref OutTotalWriter); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar escrever os dados do header no fluxo. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Consolida os dados do fluxo para o arquivo. Resultado = myCaptureAudio.StreamFile.Commit(CA_STGC.CA_STGC_CONSOLIDATE); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao consolidar os dados do header no fluxo. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Libera o fluxo e sua referencia para o arquivo. myCaptureAudio.StreamFile.LiberarReferencia(); myCaptureAudio.StreamFile.Finalizar(); myCaptureAudio.StreamFile = null; Done :; //Retorna return(Resultado); }
public CarenResult IniciarCapturaDados() { //Variavel que vai retornar o resultado. CarenResult Resultado = new CarenResult(ResultCode.ER_FAIL, false); //Define o volume de captura do volume. Resultado = myCaptureAudio.AudioCaptureVolume.SetMasterVolume(1.0f, GUID_SESSION_AUDIO); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar definir o volume de captura do dispositivo. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Cria a task responsável pela captura dos dados do dispositivo. Task_ReadDataDispositivo = new Task(async() => { //Define que está capturando dados. StatusCapturandoDados = true; //Variavies utilizadas. uint OutNextPacketSize = 0; uint SizeInBytesBuffer = 0; uint OutFramesReaded = 0; CA_AUDIOCLIENTE_BUFFERFLAGS FlagsBuffer = CA_AUDIOCLIENTE_BUFFERFLAGS.Zero; ICarenBuffer BufferSilence = new CarenBuffer(); //Define que essa thread deve ter uma latencia menor. WinFuncs._AvSetMmThreadCharacteristicsW(CA_Windows_MMCSS_Multimedia_Name_Tasks.Pro_Audio, out uint OutTaskIndex); //Define a TaskIndex na estrutura myCaptureAudio.TaskIndex = OutTaskIndex; //Abre o laço que vai ficar capturando os dados. while (StatusCapturandoDados) { //Chama o método para recuperar a quantidade de frames do proximo pacote. Resultado = myCaptureAudio.AudioCapture.GetNextPacketSize(out OutNextPacketSize); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar obter o tamanho do proximo pacote de dados do dispositivo de captura. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do laço break; } //Abre um laço que vai ler todos os dados disponiveis do pacote atual e enviar para o escritor. while (OutNextPacketSize != 0) { //Chama o método para ler os dados do dispositivo. Resultado = myCaptureAudio.AudioCapture.GetBuffer( out myCaptureAudio.BufferCapturedAudio, out OutFramesReaded, out FlagsBuffer, out _, out _); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar caturar os dados disponiveis no dispositivo de captura. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do laço break; } //Define o tamanho do buffer lido do dispositivo. SizeInBytesBuffer = OutFramesReaded * myCaptureAudio.FrameSize; //Verifica os Flags do buffer. if ((FlagsBuffer & CA_AUDIOCLIENTE_BUFFERFLAGS.AUDCLNT_BUFFERFLAGS_SILENT) != 0) { //Cria o buffer do tamanho dos dados capturados. BufferSilence.CreateBuffer(SizeInBytesBuffer); //Preenche o buffer com zeros. BufferSilence.FillBuffer(); //Envia o buffer para o escritor de dados. EnviarAmostra(ref BufferSilence, SizeInBytesBuffer); //Libera a memória utilizada pelo buffer de silencio. BufferSilence.ReleaseBuffer(); } else { //Define as informações no buffer capturado. myCaptureAudio.BufferCapturedAudio.TamanhoValido = SizeInBytesBuffer; myCaptureAudio.BufferCapturedAudio.Tamanho = SizeInBytesBuffer; myCaptureAudio.BufferCapturedAudio.SetPosition(0); //Envia o buffer para o escritor de dados. EnviarAmostra(ref myCaptureAudio.BufferCapturedAudio, SizeInBytesBuffer); } //Chama o método para liberar o buffer. Resultado = myCaptureAudio.AudioCapture.ReleaseBuffer(OutFramesReaded); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar liberar o buffer capturado anteriormente. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do laço break; } //Incrementa a quantidade de dados capturados. MyHeaderInfoFile.TotalLenghtCaptured += SizeInBytesBuffer; //Chama o método para recuperar a quantidade de frames do proximo pacote. Resultado = myCaptureAudio.AudioCapture.GetNextPacketSize(out OutNextPacketSize); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao tentar obter o tamanho do proximo pacote de dados do dispositivo de captura. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do laço break; } } //Zera o tamanho do pacote. OutNextPacketSize = 0; //Faz um pequeno delay. await Task.Delay(5); } }); //Define um tempo menor para o delay do sistema. WinFuncs._TimeBeginPeriod(5); //Chama o método para iniciar o dispositivo de captura para obter os dados. Resultado = myCaptureAudio.AudioClientConfig.Start(); //Verifica se obteve sucesso if (Resultado.StatusCode != ResultCode.SS_OK) { //A operação falhou. //Mostra uma mensagem de erro. ShowMensagem( "Ocorreu uma falha ao solicitar que o dispositivo de captura inicie a captura dos dados. Mensagem de erro -> " + Resultado.ObterMensagem((int)Resultado.HResult), true); //Sai do método goto Done; } //Inicia a task de captura. Task_ReadDataDispositivo.Start(); Done :; //Retorna o resultado. return(Resultado); }