Input vocale in DirectXVoice input in DirectX

Nota

Questo articolo si riferisce alle API native di WinRT legacy.This article relates to the legacy WinRT native APIs. Per i nuovi progetti di app native, è consigliabile usare l' API OpenXR.For new native app projects, we recommend using the OpenXR API.

Questo articolo illustra come implementare i comandi vocali e il riconoscimento di frasi brevi e frasi in un'app DirectX per la realtà mista di Windows.This article explains how to implement voice commands plus small-phrase and sentence recognition in a DirectX app for Windows Mixed Reality.

Nota

I frammenti di codice in questo articolo usano C++/CX anziché C++/WinRT conforme a C + 17, usato nel modello di progetto olografico c++.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. I concetti sono equivalenti per un progetto C++/WinRT, ma è necessario tradurre il codice.The concepts are equivalent for a C++/WinRT project, but you need to translate the code.

Usare SpeechRecognizer per il riconoscimento vocale continuoUse SpeechRecognizer for continuous speech recognition

Questa sezione descrive come usare il riconoscimento vocale continuo per abilitare i comandi vocali nell'app.This section describes how to use continuous speech recognition to enable voice commands in your app. Questa procedura dettagliata usa il codice dell'esempio HolographicVoiceInput .This walk-through uses code from the HolographicVoiceInput sample. Quando l'esempio è in esecuzione, pronunciare il nome di uno dei comandi colorati registrati per modificare il colore del cubo rotante.When the sample is running, speak the name of one of the registered color commands to change the color of the spinning cube.

Per prima cosa, creare una nuova istanza di Windows:: media:: sintesi vocale:: SpeechRecognizer .First, create a new Windows::Media::SpeechRecognition::SpeechRecognizer instance.

Da HolographicVoiceInputSampleMain:: CreateSpeechConstraintsForCurrentState:From HolographicVoiceInputSampleMain::CreateSpeechConstraintsForCurrentState:

m_speechRecognizer = ref new SpeechRecognizer();

Creare un elenco di comandi vocali per il riconoscimento da ascoltare.Create a list of speech commands for the recognizer to listen for. Qui viene costruito un set di comandi per modificare il colore di un ologramma.Here, we construct a set of commands to change the color of a hologram. Per praticità, vengono creati anche i dati che verranno usati per i comandi in un secondo momento.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));

È possibile usare parole fonetiche che potrebbero non essere presenti in un dizionario per specificare i comandi.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));

Per caricare l'elenco di comandi nell'elenco di vincoli per il riconoscimento vocale, usare un oggetto 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.
       }
   });

Sottoscrivere l'evento ResultGenerated sulla SpeechContinuousRecognitionSessiondel riconoscimento vocale.Subscribe to the ResultGenerated event on the speech recognizer's SpeechContinuousRecognitionSession. Questo evento invia una notifica all'app quando uno dei comandi è stato riconosciuto.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)
           );

Il gestore dell'evento OnResultGenerated riceve i dati dell'evento in un'istanza di SpeechContinuousRecognitionResultGeneratedEventArgs .Your OnResultGenerated event handler receives event data in a SpeechContinuousRecognitionResultGeneratedEventArgs instance. Se la confidenza è maggiore della soglia definita, l'applicazione deve tenere presente che si è verificato l'evento.If the confidence is greater than the threshold you defined, your app should note that the event happened. Salvare i dati dell'evento in modo che sia possibile utilizzarli in un ciclo di aggiornamento successivo.Save the event data so that you can use it in a later update loop.

Da 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;
       }
   }

Nel codice di esempio, viene modificato il colore del cubo dell'ologramma rotante in base al comando dell'utente.In our example code, we change the color of the spinning hologram cube according to the user's command.

Da 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;
       }
   }

Usa il riconoscimento "One-Shot"Use "one-shot" recognition

È possibile configurare un riconoscimento vocale per ascoltare frasi o frasi pronunciate dall'utente.You can configure a speech recognizer to listen for phrases or sentences that the user speaks. In questo caso, viene applicato un SpeechRecognitionTopicConstraint che indica al riconoscimento vocale il tipo di input previsto.In this case, we apply a SpeechRecognitionTopicConstraint that tells the speech recognizer what type of input to expect. Ecco un flusso di lavoro dell'app per questo scenario:Here's an app workflow for this scenario:

  1. L'app crea il SpeechRecognizer, fornisce prompt dell'interfaccia utente e inizia l'ascolto di un comando parlato.Your app creates the SpeechRecognizer, provides UI prompts, and starts listening for a spoken command.
  2. L'utente pronuncia una frase o una frase.The user speaks a phrase or sentence.
  3. Il riconoscimento della voce dell'utente si verifica e viene restituito un risultato all'app.Recognition of the user's speech occurs, and a result is returned to the app. A questo punto, l'app deve fornire un prompt dell'interfaccia utente per indicare che si è verificato il riconoscimento.At this point, your app should provide a UI prompt to indicate that recognition has occurred.
  4. A seconda del livello di confidenza a cui si desidera rispondere e del livello di confidenza del risultato del riconoscimento vocale, l'app può elaborare il risultato e rispondere nel modo appropriato.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.

Questa sezione descrive come creare un SpeechRecognizer, compilare il vincolo e restare in ascolto dell'input vocale.This section describes how to create a SpeechRecognizer, compile the constraint, and listen for speech input.

Il codice seguente compila il vincolo dell'argomento, che in questo caso è ottimizzato per la ricerca 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 la compilazione ha esito positivo, è possibile continuare con il riconoscimento vocale.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)
               {

Il risultato viene quindi restituito all'app.The result is then returned to the app. Se il risultato è sufficientemente sicuro, è possibile elaborare il comando.If we're confident enough in the result, we can process the command. Questo esempio di codice elabora i risultati con almeno una confidenza media.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"
                               );
                       }
                   }

Quando si usa il riconoscimento vocale, controllare le eccezioni che potrebbero indicare che l'utente ha disattivato il microfono nelle impostazioni relative alla privacy del 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. Questo problema può verificarsi durante l'inizializzazione o il riconoscimento.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;
       }
   });

Nota

Sono disponibili diversi SpeechRecognitionScenarios predefiniti che è possibile usare per ottimizzare il riconoscimento vocale.There are several predefined SpeechRecognitionScenarios that you can use to optimize speech recognition.

  • Per ottimizzare la dettatura, utilizzare lo scenario di dettatura.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);
    
  • Per le ricerche web vocali, utilizzare il seguente vincolo di scenario specifico per il 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);
    
  • Utilizzare il vincolo form per compilare i moduli.Use the form constraint to fill out forms. In questo caso, è preferibile applicare la propria grammatica ottimizzata per compilare il modulo.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 );
    
  • È possibile fornire la propria grammatica nel formato SRGS.You can provide your own grammar in the SRGS format.

Usa il riconoscimento continuoUse continuous recognition

Per lo scenario di dettatura continua, vedere l' esempio di codice di riconoscimento vocale di Windows 10 UWP.For the continuous-dictation scenario, see the Windows 10 UWP speech code sample.

Gestione della riduzione della qualitàHandle quality degradation

Le condizioni ambientali talvolta interferiscono con il riconoscimento vocale.Environmental conditions sometimes interfere with speech recognition. Ad esempio, la stanza potrebbe essere troppo rumorosa o l'utente potrebbe parlare troppo forte.For example, the room might be too noisy, or the user might speak too loudly. Quando possibile, l'API riconoscimento vocale fornisce informazioni sulle condizioni che hanno causato la riduzione della qualità.Whenever possible, the speech recognition API provides information about the conditions that caused the quality degradation. Queste informazioni vengono inserite nell'app tramite un evento WinRT.This information is pushed to your app through a WinRT event. Nell'esempio seguente viene illustrato come sottoscrivere questo 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)
           );

Nell'esempio di codice vengono scritte le informazioni sulle condizioni nella console di debug.In our code sample, we write the conditions information to the debug console. Un'app potrebbe voler fornire feedback all'utente tramite l'interfaccia utente, la sintesi vocale e un altro metodo.An app might want to provide feedback to the user through the UI, speech synthesis, and another method. In alternativa, potrebbe essere necessario comportarsi in modo diverso quando il discorso viene interrotto da una riduzione temporanea della qualità.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 non si usano le classi di riferimento per creare l'app DirectX, è necessario annullare la sottoscrizione all'evento prima di rilasciare o ricreare il riconoscimento vocale.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. HolographicSpeechPromptSample dispone di una routine per arrestare il riconoscimento e annullare la sottoscrizione agli eventi.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; });
           }
       });
   }

Usare la sintesi vocale per fornire richieste acusticheUse speech synthesis to provide audible prompts

Gli esempi di riconoscimento vocale olografico usano la sintesi vocale per fornire istruzioni acustiche all'utente.The holographic speech samples use speech synthesis to provide audible instructions to the user. Questa sezione illustra come creare un esempio di voce sintetizzata e riprodurlo con le API HRTF audio.This section shows how to create a synthesized voice sample and then play it back through the HRTF audio APIs.

Quando si richiede l'input di frasi, è consigliabile fornire le proprie richieste di riconoscimento vocale.We recommend providing your own speech prompts when you request phrase input. I prompt possono anche indicare quando è possibile pronunciare i comandi vocali per uno scenario di riconoscimento continuo.Prompts can also help indicate when speech commands can be spoken for a continuous-recognition scenario. Nell'esempio seguente viene illustrato come utilizzare un sintetizzatore vocale a tale scopo.The following example demonstrates how to use a speech synthesizer to do this. È anche possibile usare un clip vocale pre-registrato, un'interfaccia utente visiva o un altro indicatore degli elementi da pronunciare, ad esempio negli scenari in cui il messaggio di richiesta non è dinamico.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.

Per prima cosa, creare l'oggetto SpeechSynthesizer.First, create the SpeechSynthesizer object.

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

È anche necessaria una stringa che includa il testo da sintetizzare.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.";

Il riconoscimento vocale viene sintetizzato in modo asincrono tramite SynthesizeTextToStreamAsync.Speech is synthesized asynchronously through SynthesizeTextToStreamAsync. Qui viene avviata un'attività asincrona per sintetizzare il discorso.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
       {

La sintesi vocale viene inviata come flusso di byte.The speech synthesis is sent as a byte stream. È possibile usare il flusso di byte per inizializzare una voce XAudio2.We can use that byte stream to initialize an XAudio2 voice. Per gli esempi di codice olografico, viene riprodotto come effetto audio 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;
           }
       }

Come per il riconoscimento vocale, la sintesi vocale genera un'eccezione se si verifica un errore.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.
       }
   });

Vedere ancheSee also