-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSAPIEngine.cpp
More file actions
153 lines (133 loc) · 3.16 KB
/
SAPIEngine.cpp
File metadata and controls
153 lines (133 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "stdafx.h"
#include "SAPIEngine.h"
#pragma warning( push )
#pragma warning( disable : 4996 ) // Disable warning about deprecated 'GetVersionExW'
#include <sphelper.h>
#pragma warning( pop )
#include <string>
SAPIEngine::SAPIEngine() :
_nextRuleId(0)
{
}
SAPIEngine::~SAPIEngine()
{
shutdown();
}
SAPIEngine& SAPIEngine::getInstance()
{
static SAPIEngine instance;
return instance;
}
bool SAPIEngine::initialize()
{
bool initialized = false;
// Initialize COM
if (!FAILED(::CoInitialize(nullptr)))
{
// Use the shared speech recognition context
HRESULT hr = _recoContext.CoCreateInstance(CLSID_SpSharedRecoContext);
if (SUCCEEDED(hr))
{
// Tell the context that we are only interested in speech recognition events
_recoContext->SetInterest(SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION));
// Create a speech recognition grammar
hr = _recoContext->CreateGrammar(0, &_grammar.p);
if (SUCCEEDED(hr))
{
// Use a blank grammar for now
_grammar->ResetGrammar(SpGetUserDefaultUILanguage());
initialized = true;
}
}
}
return initialized;
}
void SAPIEngine::shutdown()
{
// Release the speech recognition interfaces
_grammar.Release();
_recoContext.Release();
// Shut down COM
::CoUninitialize();
}
void SAPIEngine::update()
{
if (!_recoContext.p)
{
return;
}
// Get all events from the Recognition Context
CSpEvent event;
while (event.GetFrom(_recoContext) == S_OK)
{
// Process valid speech recognition events
if (event.eEventId == SPEI_RECOGNITION && event.RecoResult())
{
ISpRecoResult* recognitionResult = event.RecoResult();
// Get the text string from the phrase
WCHAR* phraseText = nullptr;
HRESULT hr = recognitionResult->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, true, &phraseText, nullptr);
if (SUCCEEDED(hr))
{
// Call back to client
onRecognized(std::wstring(phraseText));
// Free the phrase memory
CoTaskMemFree(phraseText);
}
}
}
}
int SAPIEngine::addCommand(const std::wstring& command)
{
int newCommandId = -1;
if (_grammar.p)
{
// Make a unique rule ID
++_nextRuleId;
// Add a new dynamic rule to the grammar
SPSTATEHANDLE hState = 0;
HRESULT hr = _grammar->GetRule(nullptr, _nextRuleId, SPRAF_TopLevel | SPRAF_Dynamic, TRUE, &hState);
if (SUCCEEDED(hr))
{
// Add a word or sequence of words to the grammar
hr = _grammar->AddWordTransition(hState, 0, command.c_str(), L" ", SPWT_LEXICAL, 1.0f, nullptr);
if (SUCCEEDED(hr))
{
hr = _grammar->Commit(0);
if (SUCCEEDED(hr))
{
// Make the rule active
_grammar->SetRuleIdState(_nextRuleId, SPRS_ACTIVE);
// Record it in our list
_commands.push_back(std::make_pair(_nextRuleId, command));
newCommandId = _nextRuleId;
}
}
}
}
return newCommandId;
}
void SAPIEngine::setCallback(SAPICallback callbackFunc)
{
_callback = callbackFunc;
}
void SAPIEngine::onRecognized(const std::wstring& text)
{
if (_callback)
{
// Find the recognized command in our list
int foundRuleID = -1;
for (auto& p : _commands)
{
if (p.second == text)
{
foundRuleID = p.first;
break;
}
}
if (foundRuleID != -1)
{
_callback(foundRuleID, text);
}
}
}