DirectX'te ses girişi

Not

Bu makale, eski WinRT yerel API'leriyle ilgilidir. Yeni yerel uygulama projeleri için OpenXR API'sini kullanmanızı öneririz.

Bu makalede, Windows Mixed Reality için bir DirectX uygulamasında sesli komutların yanı sıra küçük tümcecik ve cümle tanımanın nasıl uygulandığı açıklanmaktadır.

Not

Bu makaledeki kod parçacıkları C++ holografik proje şablonunda kullanılan C++17 uyumlu C++/WinRT yerine C++/CX kullanır. Kavramlar C++/WinRT projesi için eşdeğerdir, ancak kodu çevirmeniz gerekir.

Sürekli konuşma tanıma için SpeechRecognizer kullanma

Bu bölümde, uygulamanızda sesli komutları etkinleştirmek için sürekli konuşma tanımanın nasıl kullanılacağı açıklanmaktadır. Bu kılavuzda HolographicVoiceInput örneğindeki kod kullanılır. Örnek çalışırken, dönen küpünün rengini değiştirmek için kayıtlı renk komutlarından birinin adını söyleyin.

İlk olarak yeni bir Windows::Media::SpeechRecognition::SpeechRecognizer örneği oluşturun.

HolographicVoiceInputSampleMain::CreateSpeechConstraintsForCurrentState'ten:

m_speechRecognizer = ref new SpeechRecognizer();

Tanıyıcının dinlemesi için konuşma komutlarının listesini oluşturun. Burada bir hologramın rengini değiştirmek için bir dizi komut oluşturacağız. Kolaylık olması için, daha sonra komutlar için kullanacağımız verileri de oluştururuz.

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));

Komutları belirtmek için sözlükte bulunmayan fonetik sözcükler kullanabilirsiniz.

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

Komut listesini konuşma tanıma kısıtlamaları listesine yüklemek için SpeechRecognitionListConstraint nesnesini kullanın.

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.
       }
   });

Konuşma tanımanın SpeechContinuousRecognitionSession üzerinde ResultGenerated olayına abone olun. Bu olay, komutlarınızdan biri tanındığında uygulamanıza bildirir.

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

OnResultGenerated olay işleyiciniz bir SpeechContinuousRecognitionResultGeneratedEventArgs örneğinde olay verilerini alır. Güvenilirlik tanımladığınız eşikten büyükse, uygulamanız olayın gerçekleştiğini not etmelidir. Sonraki bir güncelleştirme döngüsünde kullanabilmek için olay verilerini kaydedin.

HolographicVoiceInputSampleMain.cpp dosyasından:

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

Örnek kodumuzda, dönen hologram küpünün rengini kullanıcının komutuna göre değiştiriyoruz.

HolographicVoiceInputSampleMain::Update'den:

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

"Tek seferlik" tanımayı kullanma

Kullanıcının konuştuğu tümcecikleri veya cümleleri dinlemek için bir konuşma tanıyıcı yapılandırabilirsiniz. Bu durumda, konuşma tanıyıcısına ne tür bir giriş beklendiğini bildiren bir SpeechRecognitionTopicConstraint uygularız. Bu senaryo için bir uygulama iş akışı aşağıdadır:

  1. Uygulamanız SpeechRecognizer'ı oluşturur, kullanıcı arabirimi istemleri sağlar ve bir konuşulan komutu dinlemeye başlar.
  2. Kullanıcı bir tümcecik veya cümle söyler.
  3. Kullanıcının konuşma tanıması gerçekleşir ve uygulamaya bir sonuç döndürülür. Bu noktada, uygulamanızın tanımanın gerçekleştiğini belirtmek için bir kullanıcı arabirimi istemi sağlaması gerekir.
  4. Yanıt vermek istediğiniz güvenilirlik düzeyine ve konuşma tanıma sonucunun güvenilirlik düzeyine bağlı olarak, uygulamanız sonucu işleyebilir ve uygun şekilde yanıt verebilir.

Bu bölümde SpeechRecognizer oluşturma, kısıtlamayı derleme ve konuşma girişini dinleme işlemleri açıklanmaktadır.

Aşağıdaki kod, bu durumda web araması için iyileştirilmiş olan konu kısıtlamasını derler.

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)
   {

Derleme başarılı olursa konuşma tanımaya devam edebiliriz.

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)
               {

Sonuç daha sonra uygulamaya döndürülür. Sonuçtan yeterince eminsek komutu işleyebiliriz. Bu kod örneği, sonuçları en az orta düzeyde güvenle işler.

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"
                               );
                       }
                   }

Konuşma tanımayı her kullandığınızda, kullanıcının sistem gizlilik ayarlarında mikrofonu kapattığını gösterebilecek özel durumlar için watch. Başlatma veya tanıma sırasında bu durum oluşabilir.

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

Not

Konuşma tanımayı iyileştirmek için kullanabileceğiniz önceden tanımlanmış birkaç SpeechRecognitionScenarios vardır.

  • Dikteyi iyileştirmek için dikte senaryoyu kullanın.

    // Compile the dictation topic constraint, which optimizes for speech dictation.
    auto dictationConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::Dictation, "dictation");
    m_speechRecognizer->Constraints->Append(dictationConstraint);
    
  • Konuşma web aramaları için aşağıdaki web'e özgü senaryo kısıtlamasını kullanın.

    // Add a web search topic constraint to the recognizer.
    auto webSearchConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::WebSearch, "webSearch");
    speechRecognizer->Constraints->Append(webSearchConstraint);
    
  • Formları doldurmak için form kısıtlamasını kullanın. Bu durumda, formu doldurmak için en iyi duruma getirilmiş kendi dil bilgisini uygulamanız en iyisidir.

    // Add a form constraint to the recognizer.
    auto formConstraint = ref new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario::FormFilling, "formFilling");
    speechRecognizer->Constraints->Append(formConstraint );
    
  • SRGS biçiminde kendi dil bilginizi sağlayabilirsiniz.

Sürekli tanımayı kullanma

Sürekli dikte senaryosu için Windows 10 UWP konuşma kodu örneğine bakın.

Kalite düşüşüyle başa çık

Ortam koşulları bazen konuşma tanımayı engeller. Örneğin, oda çok gürültülü olabilir veya kullanıcı çok yüksek sesle konuşabilir. Mümkün olduğunda, konuşma tanıma API'si kalite düşüşlerine neden olan koşullar hakkında bilgi sağlar. Bu bilgiler bir WinRT olayı aracılığıyla uygulamanıza gönderiliyor. Aşağıdaki örnekte bu olaya nasıl abone olunacak gösterilmektedir.

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

Kod örneğimizde, hata ayıklama konsoluna koşul bilgilerini yazıyoruz. Bir uygulama kullanıcı arabirimi, konuşma sentezi ve başka bir yöntem aracılığıyla kullanıcıya geri bildirim sağlamak isteyebilir. Veya konuşmanın kalitesi geçici bir düşüşle kesildiğinde farklı davranması gerekebilir.

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

DirectX uygulamanızı oluşturmak için başvuru sınıflarını kullanmıyorsanız, konuşma tanıyıcınızı serbest bırakmadan veya yeniden oluşturmadan önce etkinlik aboneliğini kaldırmanız gerekir. HolographicSpeechPromptSample tanımayı durdurmak ve olayların aboneliğini kaldırmak için bir rutine sahiptir.

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

Sesli istemler sağlamak için konuşma sentezini kullanma

Holografik konuşma örnekleri, kullanıcıya sesli yönergeler sağlamak için konuşma sentezini kullanır. Bu bölümde, sentezlenmiş bir ses örneğinin nasıl oluşturulacağı ve ardından HRTF ses API'leri aracılığıyla nasıl yürütülacağı gösterilmektedir.

İfade girişi istediğinizde kendi konuşma istemlerinizi sağlamanızı öneririz. İstemler, sürekli tanıma senaryosu için konuşma komutlarının ne zaman konuşulabileceğini de belirtmeye yardımcı olabilir. Aşağıdaki örnekte bunu yapmak için konuşma sentezleyicisinin nasıl kullanılacağı gösterilmektedir. Ayrıca, istemin dinamik olmadığı senaryolarda, önceden kaydedilmiş bir ses klibi, görsel kullanıcı arabirimi veya söylenecekleri gösteren başka bir gösterge de kullanabilirsiniz.

İlk olarak SpeechSynthesizer nesnesini oluşturun.

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

Sentezlemek için metin içeren bir dize de gerekir.

// 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.";

Konuşma, SynthesizeTextToStreamAsync aracılığıyla zaman uyumsuz olarak sentezlenmiş. Burada, konuşmayı sentezlemek için zaman uyumsuz bir görev başlatacağız.

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

Konuşma sentezi bayt akışı olarak gönderilir. XAudio2 sesini başlatmak için bu bayt akışını kullanabiliriz. Holografik kod örneklerimiz için bunu BIR HRTF ses efekti olarak oynatıyoruz.

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

Konuşma tanımada olduğu gibi, bir sorun oluştuğunda konuşma sentezi bir özel durum oluşturur.

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

           // Handle exceptions here.
       }
   });

Ayrıca bkz.