windows下文本转语音TTS库封装
一、文本转语音实现
本文提及的文本转语音库其实很多年前写的库,最近有才时间整理才将对应库整理成文章供各位网友参考。
其实在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库封装相关推荐
- 开源(离线)中文文本转语音TTS(语音合成)工具整理
开源(离线)中文文本转语音TTS(语音合成)工具整理 目录 文章目录 目录 PaddleSpeech VoiceVox TensorFlowTTS ttskit OpenTTS eSpeak 微软 T ...
- TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作
TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作 ...
- qt文本转语音tts的使用方法,QTextToSpeech
这个功能已经被qt封装好了,在不同的操作系上封装了不同的方法. 在win7上,qt调用的是微软讲述者(microsoft speech),这个功能在原版win中是自带的,在ghost或者阉割版win中 ...
- windows下C语言使用curl库访问HTTP下载文件
一.前言 cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行.它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具.cURL还包含了用于程序开发的li ...
- UE5文本转语音TTS插件
UE4.26版本的TTS文本转语音插件,同时有UE5版本 使用起来也非常简单 在文本框输入想要发音的文字 关键的语音调用 项目下载地址:https://download.csdn.net/downlo ...
- Windows下动态链接库和静态链接库的生成以及调用
Windows下静态库和动态库的生成和调用 一.简介 二.生成静态链接库(.lib)和动态链接库(.dll) 三.静态链接库的调用 四.动态链接库的调用 动态链接库的两种调用方式 仅使用.dll文件 ...
- 文本转语音TTS(文本阅读和视频配音制作)MP3
DL-TTS 通过AI驱动引擎可将文本转化为逼真的语音并可导出MP3音频文件,它可以: (1)生成逼真的合成语音 实现与人声的语调和情感匹配的流畅.发音自然的文本转语音. (2)细化的文本转语音控制 ...
- 在Windows下使用vs2019编译libjpeg库
一.库的编译 1.下载 libjpeg 源码,这里我下载的是 jpegsr9e.zip 2.解压源码 3.进入解压后的目录,找到 makefile.vs 文件,用文本编辑器打开并编辑,找到 语句 #! ...
- Windows下文本生成图像AI画图尝鲜体验
工具库 transformers 的开源方 Hugging Face 发布了一个专注于 diffuser 模型的开源库,我们可以基于它,仅仅通过几行代码就开始生成自己的艺术作画.不过这个 diffus ...
最新文章
- Verilog初级教程(23)Verilog仿真中的显示任务
- http请求gmt时间_从Chrome源码看HTTP
- Windows 10 全新开始屏幕曝光
- core sync是什么软件_什么是Quick Sync Video
- java 查询表 并返回数据_ajax与java前后台传值及数据表查询解决一个bug的问题
- Intellij IDEA + Maven——jar项目改成war项目相互转换
- 如何使用Squid服务来构建=》传统和透明代理服务器,通俗易懂!
- .NET 6 攻略大全(一)
- 操作系统的线程和进程的区别_面试官:你熟悉多线程嘛?线程跟进程有什么区别?...
- Maven超详细配置
- 【FileOutputStream类:文档中的换行与追加】
- OPPO Reno7红丝绒新年版开售:精致虎头标识+金色镜头保护圈
- 罗永浩发文评《你好,李焕英》:一定要看!
- CCF NOI1047 寻找鞍点
- Java文件类– java.io.File
- 企业对计算机类专业人才培养方案,应用型本科计算机科学与技术专业人才培养方案探讨...
- 高三计算机专业vb试题二答案,高三计算机专业VB试题(二)
- Android Weekly #33 :这个世界的问题,在于聪明人充满疑惑,而傻子们坚信不疑
- LaTeX 设置图片caption左对齐
- 音效、配乐素材网站,免费商用
热门文章
- [附源码]SSM计算机毕业设计 宠物医院管理系统JAVA
- 上传csv文件后出现乱码
- 用PyTorch搭建卷积神经网络
- plsql和navicate有什么区别_plsql和navicat连接远程oracle(易错点)
- 转载:群联PS2251-07主控(Kingston64G)量产CD-ROM+移动磁盘模式过程记录
- 在路径没问题的情况下,组件报错Component is not found
- 最长公共子串(SA和SAM求法)
- Pinia 详细教程
- 个人成长 | 总结2018--展望2019.
- 串口编程(VS2010)