Обучение sapi: создание зашифрованных файлов wav и добавление путей к файлам в реестр - PullRequest
4 голосов
/ 18 марта 2012

Мы пытаемся провести акустическое обучение, но мы не можем создать расшифрованные аудиофайлы, как его создать? Также мы используем GetTranscript и Appendtranscript, но мы не можем получить интерфейс ISpTranscript для ISpStream, если мы открываем поток в режиме READWRITE, так как вы создаете файлы стенограммы стенограммы.

hr = SPBindToFile(L"e:\\file1.wav", SPFM_OPEN_READONLY,
    &cpStream);
hr = cpStream.QueryInterface(&cpTranscript);
// We get a error here for as E_NONINTERFACE if SPFM_OPEN_READWRITE  
hr = cpTranscript->AppendTranscript(sCorrectText);
hr = cpTranscript->GetTranscript(&pwszTranscript);
// GIVES CORRECT TRANSCRIPT 

//READING THIS AGAIN ON NEXT EXECUTION TIME DOES NOT GIVE THE TRANSCRIPT

hr = SPBindToFile(L"e:\\file1.wav", SPFM_OPEN_READONLY,
    &cpStream);
hr = cpStream.QueryInterface(&cpTranscript);
//THIS GIVE THE ERROR E_NONINTERFACE

После этого нам нужно добавить путь к файлу в реестр. Мы делаем это с помощью следующего кода.

CComPtr<ISpObjectToken> cpObjToken;



ULONG                     CSIDL_LOCAL_APPDATA = 28;
ULONG                     CSIDL_FLAG_CREATE = 32768;
GUID guid0;
LPWSTR FileName2;

hr = cpRecognizerBase->GetRecoProfile(&cpObjToken);
hr = CoCreateGuid(&guid0);
hr = cpObjToken->GetStorageFileName(guid0, L"Test",   L"F:\\sample6.wav",CSIDL_FLAG_CREATE, &FileName2);
//this code runs fine but the file is never added to the registry

Любые указатели будут оценены. Этот вопрос связан с вопросом, заданным здесь Файлы речевого обучения и регистры

Спасибо

1 Ответ

0 голосов
/ 21 февраля 2019

В этом посте я расскажу, как успешно выполнить appendTranscript и обучение речи с использованием файлов WAV (кредит Билл Хатчинсон ).Все в C++.

E_NONINTERFACE происходит, если ISPStream не имеет содержимого.Например файл был пуст;вызов не был успешным, но все равно вернул s_OK (по какой-то причине это происходит).Поэтому, как правило, я бы сначала выяснил, есть ли у потока какое-либо содержимое.Вы можете сделать это, проверив его размер:

Вот пример.Если он имеет размер 0 или какой-то абсурдно большой размер, то, очевидно, он не вернул правильное значение.Имейте в виду, что возвращаемое значение равно ULARGE_INTEGER.

STATSTG streamInfo;
cpStream->Stat(&streamInfo, STATFLAG_DEFAULT);
ULARGE_INTEGER streamSizeULI;
streamSizeULI = streamInfo.cbSize;

SPBindToFile работает только с SPFM_OPEN_READONLY и SPFM_CREATE_ALWAYS, поэтому вам придется использовать один из них.

Что касается того, как сохранить добавленную запись, кажется, что вы не можете сохранить ее напрямую, если файл wav уже существует (или, по крайней мере, я не знаю как).Если файл еще не существует, вы можете создать новый ispstream, и когда вы передаете аудиоинформацию к нему, например, голосом или микрофоном (есть множество примеров в Интернете), вы можете добавить транскрипт, и он прикрепится,Ниже приведен пример.

Добавление стенограммы в новый файл:

void recordAndAppendTranscriptInOneOperation() {
HRESULT             hr = S_OK;
CComPtr <ISpVoice>      cpVoice;
CComPtr <ISpStream>     cpStream;
CComPtr<ISpTranscript>  cpTranscript;
CSpStreamFormat         cAudioFmt;

//Create    a   SAPI    Voice   
hr  =   cpVoice.CoCreateInstance(CLSID_SpVoice);

char filePathOut[] = R"(C:\SAPI\SampleOutput\SP_Sample.wav)";

//Set   the audio   format                              
if(SUCCEEDED(hr))   
{       
    hr  =   cAudioFmt.AssignFormat(SPSF_22kHz16BitMono);    
}

//Call  SPBindToFile,   a   SAPI    helper  method,     to  bind    the audio       
if(SUCCEEDED(hr))   
{
    hr = SPBindToFile(filePathOut, SPFM_CREATE_ALWAYS, &cpStream, &cAudioFmt.FormatId(), cAudioFmt.WaveFormatExPtr());
}

//set   the output  to  cpStream    so  that    the output  audio   data    wil                             
if(SUCCEEDED(hr))   
{       
    hr = cpVoice->SetOutput(cpStream, TRUE);    
}

//Speak the text    “hello  world”  synchronously                               
if(SUCCEEDED(hr))   
{       
    hr = cpVoice->Speak(L"Hello World", SPF_DEFAULT, NULL);
}

//close the stream  
if(SUCCEEDED(hr))   
{
    PWCHAR                      pwszTranscript;
    char NewTranscriptAsString[] = R"(This is a test)";
    LPCWSTR NewTranscript = charToLPSTRW(NewTranscriptAsString);

    hr = cpStream.QueryInterface(&cpTranscript);
    hr = cpTranscript->AppendTranscript(NULL);
    hr = cpTranscript->AppendTranscript(NewTranscript);
    hr = cpTranscript->GetTranscript(&pwszTranscript);

    hr  =   cpStream->Close();  
}

//Release   the stream  and voice   object  
cpStream.Release(); 
cpVoice.Release();
 }

Билл Хатчинсон (один из связанных ниже источников) имеет некоторый код, который можетиспользоваться для обучения распознавателя без внесения изменений в реестр и т. д.Я включил его в конце этого поста.У него есть функция (TrainOne), которая обучает файл распознавателя за файлом через поток памяти.Вы можете передать ранее существующие WAV для этого.В частности, WAV с транскриптами или WAV без транскриптов и (затем предоставление транскрипта функции во время вызова).Пожалуйста, посмотрите на это, так как оно очень информативно.

Вот коллекция всех знаний, связанных с SAPI, которые я обнаружил, которые будут полезны для других, пытающихся разобраться в этом беспорядке. Я также скоро опубликую свое полное решение для обучения SAPI :

Пример обучающего кода:

Поскольку код SAPI Билла Хатчинсона является одним из немногих надежных примеров использования SAPI для обучения в Интернете, я включил его пост из Google ниже, если он одиндень удален / потерян:

#include "stdafx.h"
#include "sphelper.h"
#include <sapi.h>
#include <string.h>
//MAIN() is last function below
inline HRESULT ReturnResult(ISpRecoContext * pRecoCtxt, ISpRecoResult
** ppResult)
{
        HRESULT hr = S_OK;
        CSpEvent spEvent;
        while (S_OK == pRecoCtxt->WaitForNotifyEvent(INFINITE))
        {
                while (S_OK == spEvent.GetFrom(pRecoCtxt))
                {
                        switch (spEvent.eEventId)
                        {
                                case SPEI_RECOGNITION:
                                        *ppResult = spEvent.RecoResult();
                                        if (*ppResult)
                                        {
                                                (*ppResult)->AddRef();
                                        }
                                        return hr;
                                case [OTHER EVENTS]
                    spEvent.Clear();
        }
        return hr;
}
inline HRESULT TrainOneFile(ISpRecoContext * cpRecoCtxt, ISpRecognizer
* cpRecognizerBase, ISpRecoGrammar * cpGrammar)
{
        CComPtr<ISpStream>      cpStream;
        CComPtr<ISpRecoResult>        cpResult;
        CComPtr<ISpTranscript>  cpTranscript;
        PWCHAR                  pwszTranscript;
        HRESULT hr = S_OK;
        hr = cpStream.CoCreateInstance(CLSID_SpStream);
        // Bind a stream to an existing wavefile
        if (SUCCEEDED(hr))        {
                hr = cpStream->BindToFile(L"C:\\XX.wav",                                                        SPFM_OPEN_READONLY,
                        NULL,
                        NULL,
                        SPFEI_ALL_EVENTS);
        }
        if (SUCCEEDED(hr)){
                hr = cpStream.QueryInterface(&cpTranscript);
        }
        if (SUCCEEDED(hr)) {
                hr = cpTranscript->GetTranscript(&pwszTranscript);
        }
        //THIS IS ALTERNATE CODE FOR PREVIOUS LINE, FOR SOUND FILES THAT
DON’T HAVE A TRANSCRIPT ATTACHED
        LPCWSTR sCorrectText = L"Anyone who has spent time on a farm knows
there is a rhythm to the year.";
        if (SUCCEEDED(hr)){
                hr = cpTranscript->AppendTranscript(s);
        }
        if (SUCCEEDED(hr))        {
                hr = cpTranscript->GetTranscript(&pwszTranscript);
        }
        if(SUCCEEDED(hr)){
                hr = cpRecognizerBase->SetInput(cpStream, TRUE);
        }
        USES_CONVERSION;
        CSpDynamicString dstrText;
        if (SUCCEEDED (hr)){
                hr = cpGrammar->SetDictationState(SPRS_ACTIVE);
        }
        if (SUCCEEDED(hr)){
                hr = ReturnResult(cpRecoCtxt, &cpResult);
        }
        if (SUCCEEDED(hr)){
                hr = cpGrammar->SetDictationState( SPRS_INACTIVE );
        }
        if ((cpResult) &&(SUCCEEDED(hr))){
                hr = cpResult-
>GetText(SP_GETWHOLEPHRASE,SP_GETWHOLEPHRASE,TRUE,&dstrText,NULL);
        }
        CComPtr<ISpRecoResult2> cpResult2;
        if (SUCCEEDED(hr)){
                hr = cpResult.QueryInterface<ISpRecoResult2>(&cpResult2);
        }
        if (SUCCEEDED(hr)){
//COMMITTEXT SHOULD FORCE ADAPTATION OF MODELS TO CORRECT TEXT
//(THO IT SHOULD BE REDUNDANT WITH SETTRAININGSTATE() ?)
                hr = cpResult2-
>CommitText(SP_GETWHOLEPHRASE,SP_GETWHOLEPHRASE,sCorrectText,SPCF_DEFINITE_CORRECTION);
                cpResult.Release();
                cpResult2.Release();
        }
        return hr;
}

int _tmain(int argc, _TCHAR* argv[])
{
        HRESULT hr = S_OK;
        CComPtr<ISpRecognizer2> cpRecognizer;
        CComPtr<ISpRecoContext> cpRecoCtxt;
        CComPtr<ISpRecoGrammar> cpGrammar;
        CComPtr<ISpRecognizer> cpRecognizerBase;
        hr = ::CoInitialize(NULL);
            if (SUCCEEDED(hr)) {
                hr = cpRecognizer.CoCreateInstance(CLSID_SpInprocRecognizer);
        }
        if (SUCCEEDED(hr)){
                hr = cpRecognizer.QueryInterface<ISpRecognizer>(&cpRecognizerBase);
        }
        if (SUCCEEDED(hr)){
                hr = cpRecognizerBase->CreateRecoContext(&cpRecoCtxt);
        }
        if (cpRecoCtxt){
                hr = cpRecoCtxt->CreateGrammar(0, &cpGrammar);
        }
        if (SUCCEEDED(hr)){
                hr = cpGrammar->LoadDictation(NULL, SPLO_STATIC);
        }
        if (SUCCEEDED(hr)){
                hr = cpRecognizer->SetTrainingState(TRUE, TRUE);
        }
        if (SUCCEEDED(hr)){
                hr = cpRecoCtxt->SetNotifyWin32Event();
        }
        if (SUCCEEDED(hr)){
                hr = cpRecoCtxt->SetInterest(
                        SPFEI(SPEI_RECOGNITION)|
                        SPFEI(SPEI_HYPOTHESIS)|
                        SPFEI(SPEI_FALSE_RECOGNITION),
                        SPFEI(SPEI_RECOGNITION)|
                        SPFEI(SPEI_HYPOTHESIS)|
                        SPFEI(SPEI_FALSE_RECOGNITION));
        }
        if (SUCCEEDED(hr)){
                hr = TrainOneFile(cpRecoCtxt, cpRecognizerBase, cpGrammar);
        }
        if (SUCCEEDED(hr)){//RERUN TO CHECK FOR IMPROVEMENT
                hr = TrainOneFile(cpRecoCtxt, cpRecognizerBase, cpGrammar);
        }
        cpRecognizer->SetTrainingState(FALSE, TRUE);//should turn off and
save changes
        ::CoUninitialize();
        return 0;
}
...