- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们正在尝试进行声学训练,但无法创建转录的音频文件,如何创建?此外,我们正在使用 GetTranscript 和 Appendtranscript,但如果我们以 READWRITE 模式打开流,则无法获取 ISpStream 的 ISpTranscript 接口(interface),那么如何创建转录 wav 文件。
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
任何指针将不胜感激。此问题与此处提出的问题有关 Speech training files and registry locations
谢谢
最佳答案
In this post I address how to perform
appendTranscript
successfully, and speech training using WAV files (credit to Bill Hutchinson). Everything is inC++
.
如果 ISPStream 没有内容,就会发生 E_NONINTERFACE
。例如文件是空的;调用没有成功,但仍然返回 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();
}
Bill Hutchinson(下面的链接来源之一)有一些代码可用于执行识别器训练,而无需进行所有注册表编辑等操作。我把它包含在这篇文章的末尾。他有一个函数(TrainOne),可以通过内存流逐个文件地训练识别器。您可以将预先存在的 WAV 传递给它。具体来说,要么是带有转录本的 WAV,要么是没有转录本的 WAV,并且(然后在调用时将转录本提供给函数)。请查看它,因为它提供了很多信息。
这里是我发现的与 SAPI 相关的所有知识的集合,这对其他试图解决这个问题的人很有用。 我也会很快发布我自己的完整 SAPI 培训解决方案:
How to use the function GetStorageFileName for adding training files to registry?
Training sapi : Creating transcripted wav files and adding file paths to registry
https://groups.google.com/forum/#!topic/microsoft.public.speech_tech.sdk/fTq-PJrVd_Q
示例训练代码:
由于 Bill Hutchinson 的 SAPI 代码是如何使用 SAPI 在网络上进行培训的少数可靠示例之一,我在下面包含了他来自谷歌的帖子,以防有一天它被删除/丢失:
#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;
}
关于c++ - 训练 sapi : Creating transcripted wav files and adding file paths to registry,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9760262/
我的任务是将不是来自人类直接语音的音频文件转换为文本。 例如,如果我将“Hello there”存储在 wav 文件中,它将把它转录成文本并在屏幕上显示“Hello there”字符串。 首选任何语言
我在 C# 中为 win 7 编写了一个应用程序,它通过在 System.Speech 中使用 SharedRecognizer 使用 .NET 4.0 和 SAPI 5.4。一切都在那个环境中工作,
好的,我已经在 Windows 桌面开发论坛中提出了这个问题,但仍然没有得到答案。所以我会在这里尝试。 Microsoft Sapi 5.4 和 Microsoft Speech Platform S
首先:这不是 Delphi and SAPI 的重复项。我对“SAPI in Delphi”主题有一个具体问题。 我使用了 Delphi 2009 中出色的导入类型库指南来在组件选项板中获取 TspV
我安装了新的 SAPI5 语音。在语音程序的计算机设置中,新语音可见并可供使用。但是我的程序找不到它。为了找到它,我正在使用这部分代码,我使用 System.Speech.Synthesis 命名空间
我已经创建了一个计算机语音,我想正确对待 rate 命令。 Microsoft 白皮书对费率 (https://msdn.microsoft.com/en-us/library/ms717037(v=
请看下面的代码 main.cpp #define _ATL_APARTMENT_THREADED #include //You may derive a class from CComMod
场景: 我有 2 个命令。 1) 在谷歌上搜索“这里有任何词” 2) 打开应用程序“这里有任何单词” 问题: 既然“Search Google for”后面的词可以是任何东西,我怎么知道我要为我的 I
我是 SAPI 的新手,如果你们中的任何人能给我一个演讲来用 SAPI 文本 Hello World 示例,我将不胜感激。我知道 MS 有一些例子,如“听写”等,但我想从一个非常小的例子开始。很高兴能
我正在尝试使用 Microsoft SAPI 编写文本转语音程序。为此,我有以下代码: ISpVoice * pVoice = NULL; int main(int argc, char* argv[
我已经通过以下代码成功地在 Delphi/Lazarus 中使用 SAPI 文本转语音: procedure TForm1.Button1Click(Sender: TObject); var S
每当我尝试在我的笔记本电脑上编写任何语音识别程序时,我总是会收到如下所述的相同消息。我总是可以编译我的代码并让 Windows 窗体应用程序运行。但问题是,该程序将检测不到我的声音..程序无法运行..
我想学习 C# 的 SAPI api 来进行语音到文本识别。 我找不到任何教程。任何人都可以告诉我示例在哪里或可以在此处显示吗? 它需要支持从网络摄像头麦克风获取语音。 谢谢。 最佳答案 API 文档
有没有人知道如何使用 Microsoft 的 Windows 窗体应用程序语音识别 API 进行 STT? 最佳答案 .NET 包含一个用于语音识别的程序集。您需要添加对 的引用 System.Spe
有人能帮帮我吗?我使用 SAPI 语音文本,但我不能设置女声,这是代码,它用男声说话,但我想改变它,我想要女声 #include "stdafx.h" using namespace std; voi
我正在网上搜索如何通过 javascript 使用 SAPI 语音识别。更具体地说,我想创建一个可以在本地服务器(可能无法访问互联网)上运行的 Web 应用程序,它将文本转换为语音。 我找到了一些例子
我有一个程序要求一个人将他们想要翻译成 Al Bhed 的文本,这只是一种将字母四处移动的密码,并让 SAPI 说出来。字符串翻译得很好,但是这段代码: hr = pVoice->Speak(sTra
我正在探索在 Windows 7 Embedded 平台上同时运行的两个独立 Win32 应用程序的选项,以将它们的音频输出到音频输出设备的相应 channel (即应用程序“A”使用左声道,应用程序
当我在 C# 中使用 SpeechSynthesizer 类时,我在系统中安装了所有语音。当我在 C++ 中使用基于 COM 对象的 SAPI 时,我只得到其中的 4 个(Microsoft Anna
我真正想要实现的是这个-->假设我播放一个音频文件(使用我的应用程序),它可以从互联网流式传输/或直接从本地存储访问。现在我想将 SAPI 配置为收听此源而不是麦克风,并像往常一样将语音从音频转换为文
我是一名优秀的程序员,十分优秀!