文本转语音 TTS(MS Speech SDK)问题??

专制的网站 2011-08-05 01:16:57
如下一段代码(主要是 MyPlayText() 函数),我要的功能是将我的 一段字符串 转换成 语音流。
这段代码在 控制台程序运行时,一切OK 。但是 ,我把这个功能(即 MyPlayText() 函数)放到 Windows服务程序 里面 ,pVoice->Speak 处总是失败 ,GetLastError 返回的是 1008(试图引用不存在的令牌)。

小弟水平有限 ,不知该怎么弄了... 请大家帮帮忙 !!

PS:sdk是“SpeechSDK51.exe”,环境XP+VC6

代码:

#include <windows.h>
#include <sapi.h>
#include <wininet.h>
#include <assert.h>
#include <cstdio>
#include <sphelper.h>
#include <WCHAR.h>
#pragma comment(lib, "wininet")

void MyPlayText();

int main(int argc, char* argv[])
{
MyPlayText();

return TRUE;
}

void MyPlayText()
{
ISpeechVoice* pVoice = NULL;
ISpeechBaseStream* stream=NULL;
ISpeechAudioFormat* pFormat=NULL;
ISpeechObjectTokens* ObjectTokens=NULL;
ISpeechObjectToken* pToken=NULL;

VARIANT vt;
VARIANT vt1;
long StreamNumber;


if (FAILED(::CoInitialize(NULL)))
{
OutputDebugString("==> ::CoInitialize(NULL) failed");
return;
}

HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpeechVoice, (void**)&pVoice);
if (SUCCEEDED(hr))
{
HRESULT hr = CoCreateInstance(CLSID_SpMemoryStream, NULL, CLSCTX_ALL, IID_ISpeechBaseStream, (void**)&stream);
if (SUCCEEDED(hr))
{
try
{
OutputDebugString("-----> ----->");
stream->get_Format(&pFormat);
pFormat->put_Type(SAFT8kHz16BitMono);
pVoice->putref_AudioOutputStream(stream);
pVoice->put_AllowAudioOutputFormatChangesOnNextSet(FALSE);

pVoice->GetVoices(L"", L"", &ObjectTokens);
ObjectTokens->Item(0, &pToken);
pVoice->putref_Voice(pToken);

StreamNumber = 1000;
HRESULT hr = pVoice->Speak(L"TTTTTTaaaaaaaa", SVSFDefault, &StreamNumber);
if (SUCCEEDED(hr))
{OutputDebugString("pVoice->Speak OK");}
else
{OutputDebugString("pVoice->Speak not OK");}

memset(&vt, 0, sizeof(vt));
memset(&vt1, 0, sizeof(vt1));
hr = stream->Seek(vt, SSSPTRelativeToEnd, &vt1);
if (SUCCEEDED(hr))
{OutputDebugString("stream->Seek OK");}
else
{OutputDebugString("stream->Seek not OK");}

OutputDebugString("<----- <-----");
}
catch(...)
{
OutputDebugString("-----> some err");
}
}

pVoice-> Release();
pVoice = NULL;
}
::CoUninitialize();
}
...全文
534 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Smile_Tiger 2011-09-24
  • 打赏
  • 举报
回复
执行speak时 hr返回 0x80040154 (貌似是没有注册类别...)。


我遇到过这种情况,后来发现是控制面板的语音 一栏,要设置"文字-语音转换"属性页的语音选择 为你程序中用到的语言。

专制的网站 2011-08-11
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 saberiii 的回复:]
看你这么坚持不懈。。


你每一步都有做返回值检查吧


HRESULT hr = pVoice->Speak(L"TTTTTTaaaaaaaa", SVSFDefault, &StreamNumber);

然后到这里的时候 检查返回值返回错误把 那么hr的值是多少



为什么一定要做成服务呢
[/Quote]
XP里面“登陆-->本地系统账户” ,运行 hr返回 0x80040154 (貌似是没有注册类别...)。
这个我感觉肯定是 “登陆-->本地系统账户” 的问题,∵改成 “登陆-->此账户” ,用我的管理员账户来登陆的话 ,也OK ,但是就不能 “允许服务与桌面交互” 了... 然后又回到 14楼 上面,为什么 Svr2003 却可以差别在哪?等等...
aavv778899 2011-08-10
  • 打赏
  • 举报
回复
感觉这个问题很奇怪,帮顶...
专制的网站 2011-08-10
  • 打赏
  • 举报
回复
现在 ,发现我的代码作为 XP 的服务程序去跑 ,有问题;但是,把 exe 拷贝到 WinSrv2003 里,作为服务程序去跑,就OK...

请问是 两个操作系统的差异造成的么?? XP能否通过设置 操作系统的某个地方 ,使得我的代码不出错??

PS :
前提 :我的服务程序的 属性-->登录身份 都是设置为 “本地系统账户”,而且“允许服务与桌面交互”是 √ 着的,∵ 我的程序最终效果需要“服务与桌面交互”,所以这里不能改变 ;改变的话 ,就不能“与桌面交互”了...
okmnji98423 2011-08-10
  • 打赏
  • 举报
回复
一个用户只允许连续回复3次。
SaberIII 2011-08-10
  • 打赏
  • 举报
回复
看你这么坚持不懈。。


你每一步都有做返回值检查吧


HRESULT hr = pVoice->Speak(L"TTTTTTaaaaaaaa", SVSFDefault, &StreamNumber);

然后到这里的时候 检查返回值返回错误把 那么hr的值是多少



为什么一定要做成服务呢
xyj19871987 2011-08-10
  • 打赏
  • 举报
回复
遇到这样的问题,换个编译器先,用个更新的编译器试试
专制的网站 2011-08-08
  • 打赏
  • 举报
回复
求教 指点啊~~~
下面一段代码 是用的 ISpVoice ,同样
在 控制台程序里 打印出 “ --> pVoice->Speak OK”
在 服务程序里 打印出 “ --> pVoice->Speak not OK” ...

为啥啊??是 服务程序 不能这样弄??不能用TTS做声音转换??还是别的啥原因啊???

void MyPlayText()
{
ISpVoice* pVoice;
ISpObjectToken* pVoiceToken;
IEnumSpObjectTokens* pEnum;

// CComPtr<ISpStreamFormat> cpOldStream;

ULONG ulCount = 0;

if (FAILED(::CoInitialize(NULL)))
{
OutputDebugString("==> ::CoInitialize(NULL) failed");
return;
}

HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
if (SUCCEEDED(hr))
{
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &pEnum);

try
{
if(SUCCEEDED(hr))
hr = pEnum-> Next( 1, &pVoiceToken, NULL );

if(SUCCEEDED(hr))
hr = pVoice-> SetVoice(pVoiceToken);

OutputDebugString("==> Before pVoice->Speak");
if(SUCCEEDED(hr))
{
hr = pVoice->Speak(L"How are you?", SPF_DEFAULT, NULL);
if(SUCCEEDED(hr))
OutputDebugString(" --> pVoice->Speak OK");
else
OutputDebugString(" --> pVoice->Speak not OK");
}
OutputDebugString("==> After pVoice->Speak");

pVoiceToken->Release();
pVoiceToken=NULL;

}
catch(...)
{
OutputDebugString("==> some err");
}

pVoice-> Release();
pVoice = NULL;
}
::CoUninitialize();
}
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
例子 和 网上一些代码 都是使用 ISpVoice 的 ,而我这里用的是 ISpeechVoice 不知道有没有关系?(按理来说应该都可以的啊...)
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fandh 的回复:]
一般安装包,都会带一个demo的,你运行demo,看看能否实现tts,如果demo可以,那么,再检查自己的程序不迟!
[/Quote]
运行了Demo (C:\Program Files\Microsoft Speech SDK 5.1\Samples\CPP\TTSApp),OK的~~
fandh 2011-08-05
  • 打赏
  • 举报
回复
一般安装包,都会带一个demo的,你运行demo,看看能否实现tts,如果demo可以,那么,再检查自己的程序不迟!
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fandh 的回复:]
TTS对应的驱动什么的,装了么?我记得应该要装驱动的!
[/Quote]
是这样的么??我是安装包装好了 ,就没去管它了... 但是 我在控制台程序里是OK的啊... 服务代码有影响??
fandh 2011-08-05
  • 打赏
  • 举报
回复
TTS对应的驱动什么的,装了么?我记得应该要装驱动的!
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 saberiii 的回复:]
做成服务啊,对服务不怎么熟习,不知道他和普通的应用程序有什么区别

看你的情况 好像是应为执行环境导致的错误

试试 换成
ServiceStatus.dwServiceType =
SERVICE_WIN32_OWN_PROCESS
[/Quote]
没用... 一样的效果...........
SaberIII 2011-08-05
  • 打赏
  • 举报
回复
做成服务啊,对服务不怎么熟习,不知道他和普通的应用程序有什么区别

看你的情况 好像是应为执行环境导致的错误

试试 换成
ServiceStatus.dwServiceType =
SERVICE_WIN32_OWN_PROCESS
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 saberiii 的回复:]
放到 Windows服务程序 里 是什么 窗口界面程序?
[/Quote]
是根据“用 C 语言编写 Windows 服务程序的五个步骤”(http://www.vckbase.com/document/viewdoc/?id=1474) 改的服务程序 ,无窗口界面。

#include <windows.h>
#include <stdio.h>

#include <sapi.h>
#include <wininet.h>
#include <assert.h>
#include <sphelper.h>
#include <WCHAR.h>
#pragma comment(lib, "wininet")

#define SLEEP_TIME 5000
#define LOGFILE "C:\\MemoryStatus\\memstatus.txt"

////////////////////////////////////////////////////////////
// Declare several global variables to share
// their values across multiple functions of your program.
////////////////////////////////////////////////////////////
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

////////////////////////////////////////////////////////////
// Make the forward definitions of functions prototypes.
//
////////////////////////////////////////////////////////////
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();

void MyPlayText();
void MyPlayText1();
void ZcPrintMsg(int _i,int _j);

int WriteToLog(char* str)
{
FILE* log;
log = fopen(LOGFILE, "a+");
if (log == NULL){
OutputDebugString("Log file open failed.");
return -1;
}
fprintf(log, "%s\n", str);
fclose(log);
return 0;
}

// Service initialization
int InitService()
{
OutputDebugString("Monitoring started.");
int result;
result = WriteToLog("Monitoring started.");
return(result);
}

// Control Handler
void ControlHandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
OutputDebugString("Monitoring stopped.");
WriteToLog("Monitoring stopped.");

ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;

case SERVICE_CONTROL_SHUTDOWN:
OutputDebugString("Monitoring stopped.");
WriteToLog("Monitoring stopped.");

ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;

default:
break;
}

// Report current status
SetServiceStatus (hStatus, &ServiceStatus);

return;
}

void ServiceMain(int argc, char** argv)
{
int error;

ServiceStatus.dwServiceType =
SERVICE_WIN32;
ServiceStatus.dwCurrentState =
SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;

hStatus = RegisterServiceCtrlHandler(
"MemoryStatus",
(LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}

// Initialize Service
error = InitService();
if (error)
{
// Initialization failed
ServiceStatus.dwCurrentState =
SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// We report the running status to SCM.
ServiceStatus.dwCurrentState =
SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);

// MEMORYSTATUS memory;
// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{
/* char buffer[16];
GlobalMemoryStatus(&memory);
sprintf(buffer, "%d", memory.dwAvailPhys);

OutputDebugString(buffer);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState =
SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus,
&ServiceStatus);
return;
}
*/
MyPlayText(); // ----------- here
Sleep(SLEEP_TIME);
}


return;
}

void main(int argc, char* argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "MemoryStatus";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
}
SaberIII 2011-08-05
  • 打赏
  • 举报
回复
放到 Windows服务程序 里 是什么 窗口界面程序?
专制的网站 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 saberiii 的回复:]
服务器安装 SPEECH了吗
[/Quote]
service程序,不是 服务器..........
SaberIII 2011-08-05
  • 打赏
  • 举报
回复
服务器安装 SPEECH了吗

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧