📄 plugspeech.cpp
字号:
// ========================================================
// Speech plug (Microsoft Speech API 5.0)
//
// Design and Implementation by Floris van den Berg
// ========================================================
#include "Eplug.h"
#include "PlugSpeech.h"
// --------------------------------------------------------
void __stdcall
SAPICallback(WPARAM wparam, LPARAM lparam) {
PlugSpeech *speech = (PlugSpeech *)wparam;
EpEvent pm_event;
pm_event.reference_id = 0;
pm_event.protocol = CLSID_PROTOCOL_SYSTEM;
pm_event.size = 0;
pm_event.data = NULL;
pm_event.timeout = 0;
CSpEvent event;
while (event.GetFrom(speech->m_recotxt) == S_OK) {
switch (event.eEventId) {
case SPEI_SOUND_START :
pm_event.msg = SYSTEM_SPEECH_START;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
break;
case SPEI_SOUND_END :
speech->m_recotxt->SetVoicePurgeEvent(SPFEI(SPEI_SOUND_START));
pm_event.msg = SYSTEM_SPEECH_END;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
break;
case SPEI_FALSE_RECOGNITION:
pm_event.msg = SYSTEM_SPEECH_NOISE;
pm_event.size = 0;
pm_event.data = NULL;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
break;
case SPEI_HYPOTHESIS :
case SPEI_RECOGNITION :
SPPHRASE *phrase;
speech->m_recotxt->SetVoicePurgeEvent(SPFEI(SPEI_SOUND_START));
ISpRecoResult *result = event.RecoResult();
if (SUCCEEDED(result->GetPhrase(&phrase))) {
CSpDynamicString dstrText;
if (SUCCEEDED(result->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &dstrText, NULL))) {
// get the alternates
result->GetAlternates(phrase->Rule.ulFirstElement, phrase->Rule.ulCountOfElements, 32, speech->m_alt, &speech->m_alt_count);
for (int i = 0, j = 0; i < speech->m_alt_count - 1; ++i) {
CSpDynamicString altText;
speech->m_alt[i + 1]->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, &altText, NULL);
char *tmp = altText.CopyToChar(); // who invented this brilliant interface?
if (tmp) {
speech->m_alt_string[j++] = tmp;
CoTaskMemFree(tmp);
}
}
// output the regognized phrase
char *tmp = dstrText.CopyToChar(); // who invented this brilliant interface?
pm_event.msg = SYSTEM_DATA_IN;
pm_event.size = strlen(tmp) + 1;
pm_event.data = (unsigned char *)tmp;
pm_event.reference_id = j;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
pm_event.msg = SYSTEM_SPEECH_REGOGNITION;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
CoTaskMemFree(tmp);
} else {
pm_event.msg = SYSTEM_SPEECH_NOISE;
pm_event.size = 0;
pm_event.data = NULL;
EpDispatchEvent(speech->getGrid(), speech->getId(), &pm_event);
}
}
break;
}
}
}
// --------------------------------------------------------
PlugSpeech::PlugSpeech(Grid *grid, int id) :
inherited(grid, id) {
}
PlugSpeech::~PlugSpeech() {
}
// --------------------------------------------------------
bool
PlugSpeech::open(PlugProperties *info) {
HRESULT hr = S_OK;
CComPtr<ISpAudio> cpAudio;
while (1) {
// create a recognition engine
hr = m_engine.CoCreateInstance(CLSID_SpSharedRecognizer);
if (FAILED(hr))
break;
// create the command recognition context
hr = m_engine->CreateRecoContext(&m_recotxt);
if (FAILED(hr))
break;
// Let SR know that window we want it to send event information to, and using what message
hr = m_recotxt->SetNotifyCallbackFunction(SAPICallback, (WPARAM)this, 0);
if (FAILED(hr))
break;
// Tell SR what types of events interest us. Here we only care about command recognition.
hr = m_recotxt->SetInterest(SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_SOUND_START) | SPFEI(SPEI_SOUND_END), SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_SOUND_START) | SPFEI(SPEI_SOUND_END));
if (FAILED(hr))
break;
// do not retain audio
hr = m_recotxt->SetAudioOptions(SPAO_NONE, NULL, NULL);
if (FAILED(hr))
break;
// create a new grammar
hr = m_recotxt->CreateGrammar(0, &m_grammar);
if (FAILED(hr))
break;
// load the dictation file + set state
hr = m_grammar->LoadDictation(NULL, SPLO_STATIC);
if (FAILED(hr))
break;
hr = m_grammar->SetDictationState(SPRS_INACTIVE);
if (FAILED(hr))
break;
return true;
}
close();
return false;
}
void
PlugSpeech::close() {
// release grammar, if loaded
if (m_grammar)
m_grammar.Release();
// Release recognition context, if created
if (m_recotxt) {
m_recotxt->SetNotifySink(NULL);
m_recotxt.Release();
}
// Release recognition engine instance, if created
if (m_engine)
m_engine.Release();
}
bool
PlugSpeech::connect(const char *host, int port) {
m_grammar->SetDictationState(SPRS_ACTIVE);
return true;
}
void
PlugSpeech::disconnect() {
m_grammar->SetDictationState(SPRS_INACTIVE);
}
bool
PlugSpeech::supportsSending() {
return false;
}
void
PlugSpeech::pollProgress() {
}
void *
PlugSpeech::getReferenceData(int id) {
return (void *)m_alt_string[id].c_str();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -