一、文本转语音实现

本文提及的文本转语音库其实很多年前写的库,最近有才时间整理才将对应库整理成文章供各位网友参考。

其实在windows下自带了文本转语音以及语音识别的功能,这里由于项目中需要将报警文本信息使用语音形式转化出来,所以这里仅仅只介绍文本转语音的使用。

windows下我们将文本转语音使用的就是windows自带的COM组件,也就是TTS库,为了方便使用我将语音转文本的库封装成一个Dll库,目的也是为了后续组件化和模块化后续系统的功能,该封装库仅有三个功能:

(1)语音库的初始化

//-------------------------------------------------
//  功  能:语音库的初始化
//  参  数:
//      无
//  返回值:
//      成功返回true反之返回false
//  说  明:
//      在系统初始化的时候调用该接口与TTS_UnInit对应
//-------------------------------------------------
TTSSDK_API bool TTS_Init();

(2)本文转语音

//-------------------------------------------------
//  功  能:语音库的初始化
//  参  数:
//      【输入】content     :    需要播放的文字内容
//      【输入】size        :    播放的文字内容长度
//  返回值:
//      无
//  说  明:
//      为了性能,该接口是异步接口调用后后台自动播放
//-------------------------------------------------
TTSSDK_API void TTS_Speak(const char* content,const int size);

(3)语音库的反初始化

//-------------------------------------------------
//  功  能:语音库的反初始化
//  参  数:
//      无
//  返回值:
//      无
//  说  明:
//      在系统退出的时候调用该接口以使用资源
//-------------------------------------------------
TTSSDK_API void TTS_UnInit();

我们将重点放在第三个接口的实现上:

TTSSDK_API void TTS_Speak(const char* content,const int size)
{NetCommandPtr pCmd = boost::make_shared<CNetCommand>(boost::BOOST_BIND(CTtsInstance::Speek, content));CMessageEngine::get_mutable_instance().Post(pCmd);
}

该接口的实现是通过异步方式调用的,这里使用了boost封装的消息处理引擎处理对应的消息,其目的是为了上层应用调用的完成之后可以继续做自己的工作,而不影响上层应用,特别是UI相关的线程,因为语音播放如果是同步播放的,10几个文字播放出来(包括标点符号的停顿)大概需要6-10秒,所以该接口是做成了异步处理。

最后,我们只需要关注TTS的实例的Speek方法实现就可以了:

bool CTtsInstance::Speek(std::string text)
{// window 64[不能使用-只能调用32bit程序]if (!CTtsInstance::Prepared()){TCHAR filePath[MAX_PATH] = { 0 };GetModuleFileName(NULL, filePath, MAX_PATH);_tcsrchr(filePath, _T('\\'))[1] = _T('\0');_tcscat(filePath, _T("tts.exe"));if (-1 == _taccess(filePath, 0))return false;STARTUPINFO   si = { 0 };ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);si.dwFlags = /*STARTF_USESHOWWINDOW*/0;si.wShowWindow = /*SW_SHOW*/SW_HIDE;si.lpDesktop = NULL;PROCESS_INFORMATION   ProcessInformation;ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));if (CreateProcess(filePath, (LPTSTR)text.c_str(), NULL, NULL, FALSE,/*CREATE_NEW_CONSOLE*/0, NULL, NULL, &si, &ProcessInformation)){WaitForSingleObject(ProcessInformation.hProcess, INFINITE);::CloseHandle(ProcessInformation.hThread);::CloseHandle(ProcessInformation.hProcess);}}else{if (!m_pISpVoice)return false;// 开始进行朗读BSTR content = _com_util::ConvertStringToBSTR(text.c_str());HRESULT hr = m_pISpVoice->Speak(content, SPF_ASYNC, NULL);SysFreeString(content);}return true;
}

这里做了两部分工作:

(1)播放文本

我们使用的是语音播放COM库ISpObjectToken实现的,该组件初始化如下:

bool CTtsInstance::Init()
{// 初始化COM组件if(FAILED(::CoInitialize(NULL)))return false;if(FAILED(m_pISpVoice.CoCreateInstance(CLSID_SpVoice)))return false;// 枚举所有语音TokenCComPtr<IEnumSpObjectTokens> cpEnum;if(FAILED(SpEnumTokens(SPCAT_VOICES, L"", L"", &cpEnum)))return false;ISpObjectToken* pToken = NULL;while (cpEnum->Next(1, &pToken, NULL) == S_OK){CSpDynamicString dstrDesc;HRESULT hr = SpGetDescription(pToken, &dstrDesc);if (SUCCEEDED(hr)){m_vecISpToken.push_back(pToken);}}SetVoice(2052);return true;
}

播放的时候我们只需要调用Speak接口即可,注意因为用的是COM组件,所以字符串也需要转换为COM的BSTR字符串!

(2)64bit系统兼容

因为我的程序一般都做了32bit和64bit的windows程序(包括所有dll库),经过测试发现64bit系统是调用COM库的,但是为了兼容其他的64bit库和app调用,我也必须兼容64bit的应用,我想到的好的办法是:本地调用。

既然系统仅仅支持32bit调用,那么64bit的dll封装只需要调用32bit的库就可以了,但是64bit的dll是无法调用32bit的dll的,但是可以通过进程方式调用,所以我又将该库封装成了一个32bit的exe,然后64bit的dll调用32bit的exe。该调用如下:

     TCHAR filePath[MAX_PATH] = { 0 };GetModuleFileName(NULL, filePath, MAX_PATH);_tcsrchr(filePath, _T('\\'))[1] = _T('\0');_tcscat(filePath, _T("tts.exe"));if (-1 == _taccess(filePath, 0))return false;STARTUPINFO   si = { 0 };ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);si.dwFlags = /*STARTF_USESHOWWINDOW*/0;si.wShowWindow = /*SW_SHOW*/SW_HIDE;si.lpDesktop = NULL;PROCESS_INFORMATION   ProcessInformation;ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));if (CreateProcess(filePath, (LPTSTR)text.c_str(), NULL, NULL, FALSE,/*CREATE_NEW_CONSOLE*/0, NULL, NULL, &si, &ProcessInformation)){WaitForSingleObject(ProcessInformation.hProcess, INFINITE);::CloseHandle(ProcessInformation.hThread);::CloseHandle(ProcessInformation.hProcess);}

通过查找本地的tts.exe文件进行远程调用并传递参数给exe即可。

二、测试示例

测试实例代码如下:

int _tmain(int argc, _TCHAR* argv[])
{if(!TTS_Init()){printf("初始化语音引擎失败!\n");}while (true){TTS_Speak("尊敬的李先生,早上好!", 0);printf("尊敬的李先生,早上好!\n");Sleep(5000);}TTS_UnInit();return 0;
}

(1)32bit的程序测试如下

可以看到播放正常!

(2)64bit程序测试如下

可以看到64bit的dll被调用后播放也依然正常,只不过通过进程调用方式耗时稍微长一点,不过也只能通过这种方式兼容了。

三、注意问题

不同机器测试可以发现,阉割版本的win7是没有自带语音库的,所有初始化语音COM组件正常,所以我们需要修复语音库,这里需要32bit和64bit的语音修复库,另外也可以安装自己喜欢的语音播放库(我的是男士音,不好辨识!)

源码获取、合作、技术交流请获取如下联系方式:  
QQ交流群:961179337

微信账号:lixiang6153  
公众号:IT技术快餐  
电子邮箱:lixx2048@163.com

windows下文本转语音TTS库封装相关推荐

  1. 开源(离线)中文文本转语音TTS(语音合成)工具整理

    开源(离线)中文文本转语音TTS(语音合成)工具整理 目录 文章目录 目录 PaddleSpeech VoiceVox TensorFlowTTS ttskit OpenTTS eSpeak 微软 T ...

  2. TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作

    TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作 ...

  3. qt文本转语音tts的使用方法,QTextToSpeech

    这个功能已经被qt封装好了,在不同的操作系上封装了不同的方法. 在win7上,qt调用的是微软讲述者(microsoft speech),这个功能在原版win中是自带的,在ghost或者阉割版win中 ...

  4. windows下C语言使用curl库访问HTTP下载文件

    一.前言 cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行.它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具.cURL还包含了用于程序开发的li ...

  5. UE5文本转语音TTS插件

    UE4.26版本的TTS文本转语音插件,同时有UE5版本 使用起来也非常简单 在文本框输入想要发音的文字 关键的语音调用 项目下载地址:https://download.csdn.net/downlo ...

  6. Windows下动态链接库和静态链接库的生成以及调用

    Windows下静态库和动态库的生成和调用 一.简介 二.生成静态链接库(.lib)和动态链接库(.dll) 三.静态链接库的调用 四.动态链接库的调用 动态链接库的两种调用方式 仅使用.dll文件 ...

  7. 文本转语音TTS(文本阅读和视频配音制作)MP3

    DL-TTS 通过AI驱动引擎可将文本转化为逼真的语音并可导出MP3音频文件,它可以: (1)生成逼真的合成语音 实现与人声的语调和情感匹配的流畅.发音自然的文本转语音. (2)细化的文本转语音控制 ...

  8. 在Windows下使用vs2019编译libjpeg库

    一.库的编译 1.下载 libjpeg 源码,这里我下载的是 jpegsr9e.zip 2.解压源码 3.进入解压后的目录,找到 makefile.vs 文件,用文本编辑器打开并编辑,找到 语句 #! ...

  9. Windows下文本生成图像AI画图尝鲜体验

    工具库 transformers 的开源方 Hugging Face 发布了一个专注于 diffuser 模型的开源库,我们可以基于它,仅仅通过几行代码就开始生成自己的艺术作画.不过这个 diffus ...

最新文章

  1. Verilog初级教程(23)Verilog仿真中的显示任务
  2. http请求gmt时间_从Chrome源码看HTTP
  3. Windows 10 全新开始屏幕曝光
  4. core sync是什么软件_什么是Quick Sync Video
  5. java 查询表 并返回数据_ajax与java前后台传值及数据表查询解决一个bug的问题
  6. Intellij IDEA + Maven——jar项目改成war项目相互转换
  7. 如何使用Squid服务来构建=》传统和透明代理服务器,通俗易懂!
  8. .NET 6 攻略大全(一)
  9. 操作系统的线程和进程的区别_面试官:你熟悉多线程嘛?线程跟进程有什么区别?...
  10. Maven超详细配置
  11. 【FileOutputStream类:文档中的换行与追加】
  12. OPPO Reno7红丝绒新年版开售:精致虎头标识+金色镜头保护圈
  13. 罗永浩发文评《你好,李焕英》:一定要看!
  14. CCF NOI1047 寻找鞍点
  15. Java文件类– java.io.File
  16. 企业对计算机类专业人才培养方案,应用型本科计算机科学与技术专业人才培养方案探讨...
  17. 高三计算机专业vb试题二答案,高三计算机专业VB试题(二)
  18. Android Weekly #33 :这个世界的问题,在于聪明人充满疑惑,而傻子们坚信不疑
  19. LaTeX 设置图片caption左对齐
  20. 音效、配乐素材网站,免费商用

热门文章

  1. [附源码]SSM计算机毕业设计 宠物医院管理系统JAVA
  2. 上传csv文件后出现乱码
  3. 用PyTorch搭建卷积神经网络
  4. plsql和navicate有什么区别_plsql和navicat连接远程oracle(易错点)
  5. 转载:群联PS2251-07主控(Kingston64G)量产CD-ROM+移动磁盘模式过程记录
  6. 在路径没问题的情况下,组件报错Component is not found
  7. 最长公共子串(SA和SAM求法)
  8. Pinia 详细教程
  9. 个人成长 | 总结2018--展望2019.
  10. 串口编程(VS2010)