這可能不言而喻,但我認爲如果你沒有強大的C語言處理能力,你會發現很難與SAPI的C接口一起工作。我編寫了一個程序,幾乎完全符合您前段時間討論的測試概念。首先代碼轉儲:
#include "dirent.h"
#include <iostream>
#include <string>
#include <sapi.h>
#include <sphelper.h>
int main(int argc, char* argv[]){
DIR *dir;
struct dirent* entry;
struct stat* statbuf;
::CoInitialize(NULL);
if((dir = opendir(".")) != NULL){
while((entry = readdir(dir)) != NULL){
char extCheck[260];
strcpy(extCheck, entry->d_name);
if(strlen(extCheck) > 4 && !strcmp(strlwr(extCheck) + strlen(extCheck)-4, ".wav")){
//printf("%s\n",entry->d_name);
//1. Find the wav files
//2. Check the wavs to make sure they're the correct format
//3. Output any errors to the error log
//4. Produce the text files for the wavs
//5. Cleanup and exit
FILE* fp;
std::string fileName = std::string(entry->d_name,entry->d_name + strlen(entry->d_name)-4);
fileName += ".txt";
fp = fopen(fileName.c_str(), "w+");
HRESULT hr = S_OK;
CComPtr<ISpStream> cpInputStream;
CComPtr<ISpRecognizer> cpRecognizer;
CComPtr<ISpRecoContext> cpRecoContext;
CComPtr<ISpRecoGrammar> cpRecoGrammar;
CSpStreamFormat sInputFormat;
hr = cpRecognizer.CoCreateInstance(CLSID_SpInprocRecognizer);
hr = cpInputStream.CoCreateInstance(CLSID_SpStream);
hr = sInputFormat.AssignFormat(SPSF_16kHz16BitStereo);
std::string sInputFileName = entry->d_name;
std::wstring wInputFileName = std::wstring(sInputFileName.begin(), sInputFileName.end());
hr = cpInputStream->BindToFile(wInputFileName.c_str(), SPFM_OPEN_READONLY, &sInputFormat.FormatId(), sInputFormat.WaveFormatExPtr(), SPFEI_ALL_EVENTS);
hr = cpRecognizer->SetInput(cpInputStream, TRUE);
hr = cpRecognizer->CreateRecoContext(&cpRecoContext);
hr = cpRecoContext->CreateGrammar(NULL, &cpRecoGrammar);
hr = cpRecoGrammar->LoadDictation(NULL,SPLO_STATIC);
hr = cpRecoContext->SetNotifyWin32Event();
auto hEvent = cpRecoContext->GetNotifyEventHandle();
hr = cpRecoContext->SetInterest(SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_END_SR_STREAM), SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_END_SR_STREAM));
hr = cpRecoGrammar->SetDictationState(SPRS_ACTIVE);
BOOL fEndStreamReached = FALSE;
unsigned int timeOut = 0;
//WaitForSingleObject(hEvent, INFINITE);
while (!fEndStreamReached && S_OK == cpRecoContext->WaitForNotifyEvent(INFINITE)){
CSpEvent spEvent;
while (!fEndStreamReached && S_OK == spEvent.GetFrom(cpRecoContext)){
switch (spEvent.eEventId){
case SPEI_RECOGNITION:
{
auto pPhrase = spEvent.RecoResult();
SPPHRASE *phrase = nullptr;// new SPPHRASE();
LPWSTR* text = new LPWSTR(L"");
pPhrase->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE, text, NULL);
pPhrase->GetPhrase(&phrase);
if(phrase != NULL && phrase->pElements != NULL) {
std::wstring wRuleName = L"";
if(nullptr != phrase && phrase->Rule.pszName != NULL) {
wRuleName = phrase->Rule.pszName;
}
std::wstring recognizedText = L"";
bool firstWord = true;
for(ULONG i = 0; i < (ULONG)phrase->Rule.ulCountOfElements; ++i) {
if(phrase->pElements[i].pszDisplayText != NULL) {
std::wstring outString = phrase->pElements[i].pszDisplayText;
std::string soutString = std::string(outString.begin(), outString.end());
if(!firstWord){
soutString = " " + soutString;
firstWord = false;
}
soutString = soutString + " ";
fputs(soutString.c_str(),fp);
/*if(recognizedText != L"") {
recognizedText += L" " + outString;
} else {
recognizedText += outString;
}*/
}
}
}
delete[] text;
break;
}
case SPEI_END_SR_STREAM:
{
fEndStreamReached = TRUE;
break;
}
}
// clear any event data/object references
spEvent.Clear();
}
}
hr = cpRecoGrammar->SetDictationState(SPRS_INACTIVE);
hr = cpRecoGrammar->UnloadDictation();
hr = cpInputStream->Close();
fclose(fp);
}
}
closedir(dir);
} else {
perror("Error opening directory");
}
::CoUninitialize();
std::printf("Press any key to continue...");
std::getchar();
return 0;
}
我沒有在很長一段時間運行它,但你必須爲它工作得到dirent.h。除了試用外,我沒有其他理由玩這個圖書館。
使用提供的代碼,您可能會開始考慮在識別步驟中生成的置信度值。如果你願意,你也可以調整這個從批處理文件運行。
,我所面臨的問題有以下幾條:
- 精度是一個問題,爲了提高它,我必須培養識別器,這是將需要比我有更多的時間。
- 我發現,直接翻譯成文本並不是我真正想要的。事實證明,音素數據比較重要。有了這個,你可以形成你自己的信心計劃,並開發你自己的替代具體到你的應用程序。
- 窗口識別器雖然好,但不會識別它不知道的單詞。你必須弄清楚如何將你的詞彙添加到Windows的語音識別器詞典中。
這樣說,使用股票窗口桌面語音識別器不是一件小事。我會看看現有的一些API。如果您不僅僅限於客戶端應用程序,您最好查看其他API。
這是一個相當開放的問題,我會很高興有任何輸入,無論大小。請記住,我不是世界上最熟練的程序員。所以我可能無法掌握所有這些領域特定的術語,但我正在盡我所能。 –