Entrada de voz no DirectXVoice input in DirectX

Observação

Este artigo está relacionado às APIs nativas do WinRT herdadas.This article relates to the legacy WinRT native APIs. Para novos projetos de aplicativos nativos, é recomendável usar a API OpenXR.For new native app projects, we recommend using the OpenXR API.

Este artigo explica como implementar comandos de voz , além de reconhecimento de frase e frases pequenas em um aplicativo do DirectX para a realidade mista do Windows.This article explains how to implement voice commands plus small-phrase and sentence recognition in a DirectX app for Windows Mixed Reality.

Observação

Os trechos de código neste artigo usam C++/CX em vez de C++/WinRT em conformidade com C + +17, que é usado no modelo de projeto C++ Holographic.The code snippets in this article use C++/CX rather than C++17-compliant C++/WinRT, which is used in the C++ holographic project template. Os conceitos são equivalentes a um projeto/WinRT do C++, mas você precisa converter o código.The concepts are equivalent for a C++/WinRT project, but you need to translate the code.

Usar SpeechRecognizer para reconhecimento de fala contínuoUse SpeechRecognizer for continuous speech recognition

Esta seção descreve como usar o reconhecimento de fala contínuo para habilitar comandos de voz em seu aplicativo.This section describes how to use continuous speech recognition to enable voice commands in your app. O passo a passo usa o código do exemplo HolographicVoiceInput .This walk-through uses code from the HolographicVoiceInput sample. Quando o exemplo estiver em execução, fale o nome de um dos comandos de cor registrados para alterar a cor do cubo girando.When the sample is running, speak the name of one of the registered color commands to change the color of the spinning cube.

Primeiro, crie uma nova instância do Windows:: Media:: SpeechRecognition:: SpeechRecognizer .First, create a new Windows::Media::SpeechRecognition::SpeechRecognizer instance.

De HolographicVoiceInputSampleMain:: CreateSpeechConstraintsForCurrentState:From HolographicVoiceInputSampleMain::CreateSpeechConstraintsForCurrentState:

m_speechRecognizer = ref new SpeechRecognizer();

Crie uma lista de comandos de fala para o reconhecedor a ser escutado.Create a list of speech commands for the recognizer to listen for. Aqui, construímos um conjunto de comandos para alterar a cor de um holograma.Here, we construct a set of commands to change the color of a hologram. Para sua conveniência, também criamos os dados que usaremos para os comandos mais tarde.For convenience, we also create the data that we'll use for the commands later.

m_speechCommandList = ref new Platform::Collections::Vector<String^>();
   m_speechCommandData.clear();
   m_speechCommandList->Append(StringReference(L"white"));
   m_speechCommandData.push_back(float4(1.f, 1.f, 1.f, 1.f));
   m_speechCommandList->Append(StringReference(L"grey"));
   m_speechCommandData.push_back(float4(0.5f, 0.5f, 0.5f, 1.f));
   m_speechCommandList->Append(StringReference(L"green"));
   m_speechCommandData.push_back(float4(0.f, 1.f, 0.f, 1.f));
   m_speechCommandList->Append(StringReference(L"black"));
   m_speechCommandData.push_back(float4(0.1f, 0.1f, 0.1f, 1.f));
   m_speechCommandList->Append(StringReference(L"red"));
   m_speechCommandData.push_back(float4(1.f, 0.f, 0.f, 1.f));
   m_speechCommandList->Append(StringReference(L"yellow"));
   m_speechCommandData.push_back(float4(1.f, 1.f, 0.f, 1.f));
   m_speechCommandList->Append(StringReference(L"aquamarine"));
   m_speechCommandData.push_back(float4(0.f, 1.f, 1.f, 1.f));
   m_speechCommandList->Append(StringReference(L"blue"));
   m_speechCommandData.push_back(float4(0.f, 0.f, 1.f, 1.f));
   m_speechCommandList->Append(StringReference(L"purple"));
   m_speechCommandData.push_back(float4(1.f, 0.f, 1.f, 1.f));

Você pode usar palavras fonéticas que podem não estar em um dicionário para especificar comandos.You can use phonetic words that might not be in a dictionary to specify commands.

m_speechCommandList->Append(StringReference(L"SpeechRecognizer"));
   m_speechCommandData.push_back(float4(0.5f, 0.1f, 1.f, 1.f));

Para carregar a lista de comandos na lista de restrições do reconhecedor de fala, use um objeto SpeechRecognitionListConstraint .To load the commands list into the list of constraints for the speech recognizer, use a SpeechRecognitionListConstraint object.

SpeechRecognitionListConstraint^ spConstraint = ref new SpeechRecognitionListConstraint(m_speechCommandList);
   m_speechRecognizer->Constraints->Clear();
   m_speechRecognizer->Constraints->Append(spConstraint);
   create_task(m_speechRecognizer->CompileConstraintsAsync()).then([this](SpeechRecognitionCompilationResult^ compilationResult)
   {
       if (compilationResult->Status == SpeechRecognitionResultStatus::Success)
       {
           m_speechRecognizer->ContinuousRecognitionSession->StartAsync();
       }
       else
       {
           // Handle errors here.
       }
   });

Assine o evento ResultGenerated no SpeechContinuousRecognitionSessiondo reconhecedor de fala.Subscribe to the ResultGenerated event on the speech recognizer's SpeechContinuousRecognitionSession. Esse evento notifica seu aplicativo quando um de seus comandos for reconhecido.This event notifies your app when one of your commands has been recognized.

m_speechRecognizer->ContinuousRecognitionSession->ResultGenerated +=
       ref new TypedEventHandler<SpeechContinuousRecognitionSession^, SpeechContinuousRecognitionResultGeneratedEventArgs^>(
           std::bind(&HolographicVoiceInputSampleMain::OnResultGenerated, this, _1, _2)
           );

O manipulador de eventos OnResultGenerated recebe dados de evento em uma instância SpeechContinuousRecognitionResultGeneratedEventArgs .Your OnResultGenerated event handler receives event data in a SpeechContinuousRecognitionResultGeneratedEventArgs instance. Se a confiança for maior que o limite definido, seu aplicativo deverá observar que o evento ocorreu.If the confidence is greater than the threshold you defined, your app should note that the event happened. Salve os dados do evento para que você possa usá-los em um loop de atualização posterior.Save the event data so that you can use it in a later update loop.

De HolographicVoiceInputSampleMain. cpp:From HolographicVoiceInputSampleMain.cpp:

// Change the cube color, if we get a valid result.
   void HolographicVoiceInputSampleMain::OnResultGenerated(SpeechContinuousRecognitionSession ^sender, SpeechContinuousRecognitionResultGeneratedEventArgs ^args)
   {
       if (args->Result->RawConfidence > 0.5f)
       {
           m_lastCommand = args->Result->Text;
       }
   }

Em nosso código de exemplo, alteramos a cor do cubo de holograma girando de acordo com o comando do usuário.In our example code, we change the color of the spinning hologram cube according to the user's command.

De HolographicVoiceInputSampleMain:: Update:From HolographicVoiceInputSampleMain::Update:

// Check for new speech input since the last frame.
   if (m_lastCommand != nullptr)
   {
       auto command = m_lastCommand;
       m_lastCommand = nullptr;

       int i = 0;
       for each (auto& iter in m_speechCommandList)
       {
           if (iter == command)
           {
               m_spinningCubeRenderer->SetColor(m_speechCommandData[i]);
               break;
           }

           ++i;
       }
   }

Usar o reconhecimento "One-shot"Use "one-shot" recognition

Você pode configurar um reconhecedor de fala para escutar frases ou frases que o usuário fala.You can configure a speech recognizer to listen for phrases or sentences that the user speaks. Nesse caso, aplicamos um SpeechRecognitionTopicConstraint que informa ao reconhecedor de fala o tipo de entrada a ser esperado.In this case, we apply a SpeechRecognitionTopicConstraint that tells the speech recognizer what type of input to expect. Aqui está um fluxo de trabalho de aplicativo para este cenário:Here's an app workflow for this scenario:

  1. Seu aplicativo cria o SpeechRecognizer, fornece prompts de interface do usuário e começa a escutar um comando falado.Your app creates the SpeechRecognizer, provides UI prompts, and starts listening for a spoken command.
  2. O usuário fala uma frase ou frase.The user speaks a phrase or sentence.
  3. O reconhecimento da fala do usuário ocorre e um resultado é retornado para o aplicativo.Recognition of the user's speech occurs, and a result is returned to the app. Neste ponto, seu aplicativo deve fornecer um prompt de interface do usuário para indicar que o reconhecimento ocorreu.At this point, your app should provide a UI prompt to indicate that recognition has occurred.
  4. Dependendo do nível de confiança que você deseja responder e do nível de confiança do resultado do reconhecimento de fala, seu aplicativo poderá processar o resultado e responder conforme apropriado.Depending on the confidence level that you want to respond to and the confidence level of the speech recognition result, your app can process the result and respond as appropriate.

Esta seção descreve como criar um SpeechRecognizer, compilar a restrição e ouvir a entrada de fala.This section describes how to create a SpeechRecognizer, compile the constraint, and listen for speech input.

O código a seguir compila a restrição de tópico, que nesse caso é otimizada para pesquisa na Web.The following code compiles the topic constraint, which in this case is optimized for web search.

auto constraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::WebSearch, L"webSearch");
   m_speechRecognizer->Constraints->Clear();
   m_speechRecognizer->Constraints->Append(constraint);
   return create_task(m_speechRecognizer->CompileConstraintsAsync())
       .then([this](task<SpeechRecognitionCompilationResult^> previousTask)
   {

Se a compilação for realizada com sucesso, podemos continuar com o reconhecimento de fala.If compilation succeeds, we can continue with speech recognition.

try
       {
           SpeechRecognitionCompilationResult^ compilationResult = previousTask.get();

           // Check to make sure that the constraints were in a proper format and the recognizer was able to compile it.
           if (compilationResult->Status == SpeechRecognitionResultStatus::Success)
           {
               // If the compilation succeeded, we can start listening for the user's spoken phrase or sentence.
               create_task(m_speechRecognizer->RecognizeAsync()).then([this](task<SpeechRecognitionResult^>& previousTask)
               {

O resultado é retornado para o aplicativo.The result is then returned to the app. Se estivermos confiantes o suficiente no resultado, podemos processar o comando.If we're confident enough in the result, we can process the command. Este exemplo de código processa resultados com pelo menos confiança média.This code example processes results with at least medium confidence.

try
                   {
                       auto result = previousTask.get();

                       if (result->Status != SpeechRecognitionResultStatus::Success)
                       {
                           PrintWstringToDebugConsole(
                               std::wstring(L"Speech recognition was not successful: ") +
                               result->Status.ToString()->Data() +
                               L"\n"
                               );
                       }

                       // In this example, we look for at least medium confidence in the speech result.
                       if ((result->Confidence == SpeechRecognitionConfidence::High) ||
                           (result->Confidence == SpeechRecognitionConfidence::Medium))
                       {
                           // If the user said a color name anywhere in their phrase, it will be recognized in the
                           // Update loop; then, the cube will change color.
                           m_lastCommand = result->Text;

                           PrintWstringToDebugConsole(
                               std::wstring(L"Speech phrase was: ") +
                               m_lastCommand->Data() +
                               L"\n"
                               );
                       }
                       else
                       {
                           PrintWstringToDebugConsole(
                               std::wstring(L"Recognition confidence not high enough: ") +
                               result->Confidence.ToString()->Data() +
                               L"\n"
                               );
                       }
                   }

Sempre que usar o reconhecimento de fala, observe as exceções que podem indicar que o usuário desativou o microfone nas configurações de privacidade do sistema.Whenever you use speech recognition, watch for exceptions that could indicate that the user has turned off the microphone in the system privacy settings. Isso pode ocorrer durante a inicialização ou o reconhecimento.This can happen during initialization or recognition.

catch (Exception^ exception)
                   {
                       // Note that if you get an "Access is denied" exception, you might need to enable the microphone
                       // privacy setting on the device and/or add the microphone capability to your app manifest.

                       PrintWstringToDebugConsole(
                           std::wstring(L"Speech recognizer error: ") +
                           exception->ToString()->Data() +
                           L"\n"
                           );
                   }
               });

               return true;
           }
           else
           {
               OutputDebugStringW(L"Could not initialize predefined grammar speech engine!\n");

               // Handle errors here.
               return false;
           }
       }
       catch (Exception^ exception)
       {
           // Note that if you get an "Access is denied" exception, you might need to enable the microphone
           // privacy setting on the device and/or add the microphone capability to your app manifest.

           PrintWstringToDebugConsole(
               std::wstring(L"Exception while trying to initialize predefined grammar speech engine:") +
               exception->Message->Data() +
               L"\n"
               );

           // Handle exceptions here.
           return false;
       }
   });

Observação

Há vários SpeechRecognitionScenarios predefinidos que você pode usar para otimizar o reconhecimento de fala.There are several predefined SpeechRecognitionScenarios that you can use to optimize speech recognition.

  • Para otimizar o ditado, use o cenário de ditado.To optimize for dictation, use the dictation scenario.

    // Compile the dictation topic constraint, which optimizes for speech dictation.
    auto dictationConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::Dictation, "dictation");
    m_speechRecognizer->Constraints->Append(dictationConstraint);
    
  • Para pesquisas na Web de fala, use a seguinte restrição de cenário específica da Web.For speech web searches, use the following web-specific scenario constraint.

    // Add a web search topic constraint to the recognizer.
    auto webSearchConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::WebSearch, "webSearch");
    speechRecognizer->Constraints->Append(webSearchConstraint);
    
  • Use a restrição formulário para preencher formulários.Use the form constraint to fill out forms. Nesse caso, é melhor aplicar sua própria gramática otimizada para preencher o formulário.In this case, it's best to apply your own grammar that's optimized for filling out the form.

    // Add a form constraint to the recognizer.
    auto formConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::FormFilling, "formFilling");
    speechRecognizer->Constraints->Append(formConstraint );
    
  • Você pode fornecer sua própria gramática no formato SRGS.You can provide your own grammar in the SRGS format.

Usar reconhecimento contínuoUse continuous recognition

Para o cenário de ditado contínuo, consulte o exemplo de código de fala do UWP do Windows 10.For the continuous-dictation scenario, see the Windows 10 UWP speech code sample.

Lidar com a degradação da qualidadeHandle quality degradation

Às vezes, as condições ambientais interferem no reconhecimento de fala.Environmental conditions sometimes interfere with speech recognition. Por exemplo, a sala pode estar muito ruidosa ou o usuário pode falar muito alto.For example, the room might be too noisy, or the user might speak too loudly. Sempre que possível, a API de reconhecimento de fala fornece informações sobre as condições que causaram a degradação da qualidade.Whenever possible, the speech recognition API provides information about the conditions that caused the quality degradation. Essas informações são enviadas por push para seu aplicativo por meio de um evento do WinRT.This information is pushed to your app through a WinRT event. O exemplo a seguir mostra como assinar esse evento.The following example shows how to subscribe to this event.

m_speechRecognizer->RecognitionQualityDegrading +=
       ref new TypedEventHandler<SpeechRecognizer^, SpeechRecognitionQualityDegradingEventArgs^>(
           std::bind(&HolographicVoiceInputSampleMain::OnSpeechQualityDegraded, this, _1, _2)
           );

Em nosso exemplo de código, escrevemos as informações de condições no console de depuração.In our code sample, we write the conditions information to the debug console. Um aplicativo pode querer fornecer comentários ao usuário por meio da interface do usuário, síntese de fala e outro método.An app might want to provide feedback to the user through the UI, speech synthesis, and another method. Ou talvez seja necessário se comportar de maneira diferente quando a fala é interrompida por uma redução temporária na qualidade.Or it might need to behave differently when speech is interrupted by a temporary reduction in quality.

void HolographicSpeechPromptSampleMain::OnSpeechQualityDegraded(SpeechRecognizer^ recognizer, SpeechRecognitionQualityDegradingEventArgs^ args)
   {
       switch (args->Problem)
       {
       case SpeechRecognitionAudioProblem::TooFast:
           OutputDebugStringW(L"The user spoke too quickly.\n");
           break;

       case SpeechRecognitionAudioProblem::TooSlow:
           OutputDebugStringW(L"The user spoke too slowly.\n");
           break;

       case SpeechRecognitionAudioProblem::TooQuiet:
           OutputDebugStringW(L"The user spoke too softly.\n");
           break;

       case SpeechRecognitionAudioProblem::TooLoud:
           OutputDebugStringW(L"The user spoke too loudly.\n");
           break;

       case SpeechRecognitionAudioProblem::TooNoisy:
           OutputDebugStringW(L"There is too much noise in the signal.\n");
           break;

       case SpeechRecognitionAudioProblem::NoSignal:
           OutputDebugStringW(L"There is no signal.\n");
           break;

       case SpeechRecognitionAudioProblem::None:
       default:
           OutputDebugStringW(L"An error was reported with no information.\n");
           break;
       }
   }

Se você não estiver usando classes de referência para criar seu aplicativo DirectX, deverá cancelar a assinatura do evento antes de liberar ou recriar seu reconhecedor de fala.If you're not using ref classes to create your DirectX app, you must unsubscribe from the event before you release or recreate your speech recognizer. O HolographicSpeechPromptSample tem uma rotina para parar o reconhecimento e cancelar a assinatura de eventos.The HolographicSpeechPromptSample has a routine to stop recognition and unsubscribe from events.

Concurrency::task<void> HolographicSpeechPromptSampleMain::StopCurrentRecognizerIfExists()
   {
       return create_task([this]()
       {
           if (m_speechRecognizer != nullptr)
           {
               return create_task(m_speechRecognizer->StopRecognitionAsync()).then([this]()
               {
                   m_speechRecognizer->RecognitionQualityDegrading -= m_speechRecognitionQualityDegradedToken;

                   if (m_speechRecognizer->ContinuousRecognitionSession != nullptr)
                   {
                       m_speechRecognizer->ContinuousRecognitionSession->ResultGenerated -= m_speechRecognizerResultEventToken;
                   }
               });
           }
           else
           {
               return create_task([this]() { m_speechRecognizer = nullptr; });
           }
       });
   }

Usar a síntese de fala para fornecer prompts audíveisUse speech synthesis to provide audible prompts

Os exemplos de fala do Holographic usam a síntese de fala para fornecer instruções audíveis ao usuário.The holographic speech samples use speech synthesis to provide audible instructions to the user. Esta seção mostra como criar um exemplo de voz sintetizada e reproduzi-lo novamente por meio das APIs de áudio do HRTF.This section shows how to create a synthesized voice sample and then play it back through the HRTF audio APIs.

É recomendável fornecer seus próprios prompts de fala ao solicitar entrada de frase.We recommend providing your own speech prompts when you request phrase input. Os prompts também podem ajudar a indicar quando os comandos de fala podem ser falados para um cenário de reconhecimento contínuo.Prompts can also help indicate when speech commands can be spoken for a continuous-recognition scenario. O exemplo a seguir demonstra como usar um sintetizador de fala para fazer isso.The following example demonstrates how to use a speech synthesizer to do this. Você também pode usar um clipe de voz previamente gravado, uma interface do usuário visual ou outro indicador do que dizer, por exemplo, em cenários em que o prompt não é dinâmico.You could also use a pre-recorded voice clip, a visual UI, or another indicator of what to say, for example in scenarios where the prompt isn't dynamic.

Primeiro, crie o objeto SpeechSynthesizer.First, create the SpeechSynthesizer object.

auto speechSynthesizer = ref new Windows::Media::SpeechSynthesis::SpeechSynthesizer();

Você também precisa de uma cadeia de caracteres que inclua o texto a ser sintetizado.You also need a string that includes the text to synthesize.

// Phrase recognition works best when requesting a phrase or sentence.
   StringReference voicePrompt = L"At the prompt: Say a phrase, asking me to change the cube to a specific color.";

A fala é sintetizada de forma assíncrona por meio de SynthesizeTextToStreamAsync.Speech is synthesized asynchronously through SynthesizeTextToStreamAsync. Aqui, iniciamos uma tarefa assíncrona para sintetizar a fala.Here, we start an async task to synthesize the speech.

create_task(speechSynthesizer->SynthesizeTextToStreamAsync(voicePrompt), task_continuation_context::use_current())
       .then([this, speechSynthesizer](task<Windows::Media::SpeechSynthesis::SpeechSynthesisStream^> synthesisStreamTask)
   {
       try
       {

A síntese de fala é enviada como um fluxo de bytes.The speech synthesis is sent as a byte stream. Podemos usar esse fluxo de bytes para inicializar uma voz XAudio2.We can use that byte stream to initialize an XAudio2 voice. Para nossos exemplos de código Holographic, vamos reproduzi-lo como um efeito de áudio HRTF.For our holographic code samples, we play it back as an HRTF audio effect.

Windows::Media::SpeechSynthesis::SpeechSynthesisStream^ stream = synthesisStreamTask.get();

           auto hr = m_speechSynthesisSound.Initialize(stream, 0);
           if (SUCCEEDED(hr))
           {
               m_speechSynthesisSound.SetEnvironment(HrtfEnvironment::Small);
               m_speechSynthesisSound.Start();

               // Amount of time to pause after the audio prompt is complete, before listening
               // for speech input.
               static const float bufferTime = 0.15f;

               // Wait until the prompt is done before listening.
               m_secondsUntilSoundIsComplete = m_speechSynthesisSound.GetDuration() + bufferTime;
               m_waitingForSpeechPrompt = true;
           }
       }

Assim como com o reconhecimento de fala, a síntese de fala gera uma exceção se algo der errado.As with speech recognition, speech synthesis throws an exception if something goes wrong.

catch (Exception^ exception)
       {
           PrintWstringToDebugConsole(
               std::wstring(L"Exception while trying to synthesize speech: ") +
               exception->Message->Data() +
               L"\n"
               );

           // Handle exceptions here.
       }
   });

Confira tambémSee also