TTS中英文混合朗读的完全设计实现
中英文混合朗读一直是个难点,即在一段文本中要将中文和英文分离出来进行分别朗读,又不能打乱朗读的次序,所以我们设计如下的两种方法,每种方法都有各自的优点和缺点。
①采用同步朗读方式进行混合朗读:
将朗读文本进行提取分析,提取本文本中的中文和英文,在编程中,我们设定两个标志:
const int IsEnglish = 0; // 英文标志
const int IsChinese = 3; // 中文标志
标点符号和数字默认和它前面的字的标志一致。当处理文本时标志发生改变时,立即调用语音合成引擎进行朗读。
//循环遍历每个字
for (int i = 0; i < length; i++)
{
//提取字母
current = m_strTxt.GetAt(i);
// 如果是英文字母,标志设为0
if((current >= 'A' && current <= 'Z') || (current >= 'a' && current <= 'z'))
{
CFlag = IsEnglish; // 如果是英文字母,标志设为0
}
else if((current >=0&¤t<= 64)||(current >=91&&
current<= 96)||(current >=123&¤t<= 127))
//如果是数字则和它的前一个字母的标志一样
{
if(PFlag==IsEnglish)
CFlag=IsEnglish;//英文标志
else
CFlag=IsChinese;//中文标志
}
else
{
CFlag = IsChinese;//中文标志
}
if (CFlag == PFlag) //若当前标志与前一个字母标志相同则个数增一
iCount++;
else
{
if (iCount!=0) //字符类型变化,读出前面的文本
{
if(PFlag==IsEnglish)
SetVoice(szwEnglish);//将引擎设置成英文引擎
else
SetVoice(szwChinese);//将引擎设置成中文引擎
str = m_strTxt.Mid(first,iCount);//提取出标志相同的文字
//设置成同步朗读方式,将文本同步朗读出来
hr = m_IpVoice->Speak(str.AllocSysString(), 0, 0 );
}
PFlag = CFlag;//改变当前标志
first = i; //设置当前位置
iCount = 1;//个数还原为1
}
}
//读出最后一段文本
if(PFlag==IsEnglish)
SetVoice(szwEnglish);//将引擎设置成英文引擎
else
SetVoice(szwChinese);//将引擎设置成中文引擎
str = m_strTxt.Mid(first,length);
//设置成同步朗读方式,将文本同步朗读出来
hr = m_IpVoice->Speak(str.AllocSysString(), 0, 0 );
②采用异步XML格式进行混合朗读:
将第二种方式与第一中方式相似,区别只是在于它是将文本进一步进行处理,最后生成符合XML朗读格式的文本后对文本进行朗读,而不是调用当标志发生改变时立即调用语音合成引擎进行朗读:
//设置XML起始标志
strEngine.printf("<xml version=/"1.0/">/n<SAPI>/n
<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
for (int i = 1; i <= nLength; i++)
{
......
if (iCount!=0) //字符类型变化,进行文本处理
{
if(PFlag==IsChinese)//中文标志
{
//将中文朗读文本XML格式插入文本中
strWord+="</VOICE>/n";
strEngine.printf("
<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
}
else
{
//将英文朗读文本XML格式插入文本中
strWord+="</VOICE>/n";
strEngine.printf(
"<VOICE REQUIRED=/"NAME=%s/">",m_strENEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
}
}
......
}
//读出最后一段文本
if(PFlag==IsChinese)
{
strWord+="</VOICE>/n";
strEngine.printf("
<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
//添加xml结束标志
strEngine="</VOICE>/n</SAPI>/n</xml>";
strWord+=strEngine;
}
else
{
//将英文朗读文本XML格式插入文本中
strWord+="</VOICE>/n";
strEngine.printf("
<VOICE REQUIRED=/"NAME=%s/">",m_strENEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
//添加xml结束标志
strEngine="</VOICE>/n</SAPI>/n</xml>";
strWord+=strEngine;
}
//采用XML和异步朗读方式朗读文本
TTS_Speak(strWord.c_str(),IS_MIX_SPEECH|IS_ASY_SPEECH);
}
当然上面的两种方式各有各的优缺点,第一种方式处理较快,但是不能进行异步朗读,同步朗读时不能进行其它操作,而且频繁调用语音引擎进行声音设置容易造成内存占有率较高。第二种方法需要对文本进行插入处理比较耗时,且要求开发者要对XML语音朗读格式有一定的了解所以开发比较复杂,但它是可以进行异步朗读,使你在朗读的时候还能进行其他操作,且采用XML朗读方式,使你不用人为的去改变引擎的声音,将操作交给系统进行处理摆脱了频繁改变声音后造成的内存占有率较高的问题!
具体源码如下:
①采用VC开发的:
//函数 名:HRESULT CText2Speech::MixSpeech(char *speech)
//编写 者:南才北往
//参考资料: Speech SDK5.1 帮助文档
//函数功能:语音合成朗读--混合朗读.
//输入参数:char* speech - 文本朗读内容
//返回 值:S_OK - 成功 ; E_FAIL -失败
//备 注: 无
///
HRESULT CText2Speech::MixSpeech(char *speech)
{
long length;
HRESULT hr;
CString m_strTxt=speech,str;
char current;
int PFlag, CFlag;
int iCount, first;
const int IsEnglish = 0; // 英文标志
const int IsChinese = 3; // 中文标志
length = m_strTxt.GetLength();
PFlag = IsChinese;
iCount=0;
first=0;
for (int i = 0; i < length; i++)
{
current = m_strTxt.GetAt(i);
if((current >= 'A' && current <= 'Z') || (current >= 'a' && current <= 'z'))
{
CFlag = IsEnglish; // 如果是英文字母,标志设为0
}
else if((current >=0&¤t<= 64)||(current >=91&¤t<= 96)||(current >=123&¤t<= 127))//如果是数字则和它的前一个字母的标志一样
{
if(PFlag==IsEnglish)
CFlag=IsEnglish;
else
CFlag=IsChinese;
}
else
{
CFlag = IsChinese;
}
if (CFlag == PFlag)
iCount++;
else
{
if (iCount!=0) //字符类型变化,读出前面的文本
{
if(PFlag==IsEnglish)
SetVoice(szwEnglish);
else
SetVoice(szwChinese);
str = m_strTxt.Mid(first,iCount);
hr = m_IpVoice->Speak(str.AllocSysString(), 0, 0 );
}
PFlag = CFlag;
first = i;
iCount = 1;
}
}
//读出最后一段文本
if(PFlag==IsEnglish)
SetVoice(szwEnglish);
else
SetVoice(szwChinese);
str = m_strTxt.Mid(first,length);
hr = m_IpVoice->Speak(str.AllocSysString(), 0, 0 );
return hr;
}
②采用c++builder开发的
//函数 名:void __fastcall TForm1::MixSpeech()
//编写 者:南才北往
//参考资料: Speech SDK5.1 帮助文档
//函数功能:语音合成朗读--混合朗读.
//输入参数:Edit1->Text - 文本朗读内容
//返回 值:无
//备 注: 无
///
void __fastcall TForm1::MixSpeech()
{
int nLength;
char chCurrent;
AnsiString strTemp,strWord;
AnsiString strEngine; //语音引擎名称
strTemp=Edit1->Text;
nLength=strTemp.Length();
int PFlag, CFlag;
int iCount, first;
const int IsEnglish = 0; // 英文标志
const int IsChinese = 3; // 中文标志
PFlag = IsChinese;
iCount=0;
first=1;
strEngine.printf("<xml version=/"1.0/">/n<SAPI>/n<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
for (int i = 1; i <= nLength; i++)
{
chCurrent=strTemp.operator [](i);
if((chCurrent >= 'A' && chCurrent <= 'Z') || (chCurrent >= 'a' && chCurrent <= 'z'))
{
CFlag = IsEnglish; // 如果是英文字母,标志设为0
}
else if((chCurrent >=0&&chCurrent<= 64)||
(chCurrent >=91&&chCurrent<= 96)||
(chCurrent >=123&&chCurrent< 127))//如果是数字则和它的前一个字母的标志一样
{
if(PFlag==IsEnglish)
CFlag=IsEnglish;
else
CFlag=IsChinese;
}
else
{
CFlag = IsChinese;
}
if (CFlag == PFlag)
iCount++;
else
{
if (iCount!=0) //字符类型变化,读出前面的文本
{
if(PFlag==IsChinese)
{
strWord+="</VOICE>/n";
strEngine.printf("<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
}
else
{
strWord+="</VOICE>/n";
strEngine.printf("<VOICE REQUIRED=/"NAME=%s/">",m_strENEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
}
}
PFlag = CFlag;
first = i;
iCount = 1;
}
}
//读出最后一段文本
if(PFlag==IsChinese)
{
strWord+="</VOICE>/n";
strEngine.printf("<VOICE REQUIRED=/"NAME=%s/">",m_strZHEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
strEngine="</VOICE>/n</SAPI>/n</xml>";
strWord+=strEngine;
}
else
{
strWord+="</VOICE>/n";
strEngine.printf("<VOICE REQUIRED=/"NAME=%s/">",m_strENEngine.c_str());
strWord+=strEngine;
strWord+=strTemp.SubString(first,iCount);
strEngine="</VOICE>/n</SAPI>/n</xml>";
strWord+=strEngine;
}
TTS_Speak(strWord.c_str(),IS_XML_SPEECH|IS_ASY_SPEECH);
//ShowMessage(strWord);
}
TTS中英文混合朗读的完全设计实现相关推荐
- C#中英文混合朗读文本代码
//首先要引用一个类库SpeechLib.dll using System; using System.Collections.Generic; using System.Windows.Forms; ...
- PaddleSpeech 实现多种卡通音色和方言的中英文混合 TTS
(以下内容搬运自 PaddleSpeech) 实现单模型TTS中英文发音初步尝试了3种方案:单发音人方式.多发音人语料混合方式.finetune方式. 示例句子: 大家好,我是parrot虚拟老师,我 ...
- C#WPF 语音开发教程 TTS中英文语音(男女声音)朗读 源代码下载 csdn tts(text to sound) 一步一步 教你制作语音软件 附图和源代码
C#WPF 语音开发教程 TTS中文语音朗读 一步一步 教你制作语音软件 附图和源代码 使用时,请确认电脑喇叭打开,并且不是静音额. 效果展示 一 项目准备 1.vs2012开发平台 2.微软的语 ...
- Lua截取utf-8编码的中英文混合字符串
参考博客:UTF8字符串在lua的截取和字数统计[转载] 需求 按字面个数来截取子字符串 函数(字符串, 开始位置, 截取长度)utf8sub("你好1世界哈哈",2,5) = 好 ...
- PaddleOCR加载chinese_ocr_db_crnn_modile模型进行中英文混合预测(Http服务)实践
1. 环境搭建 参考:<PaddleOCR加载chinese_ocr_db_crnn_server模型进行中英文混合预测(命令行)实践> 2. 服务端部署 hub serving star ...
- PaddleOCR加载chinese_ocr_db_crnn_server/chinese_ocr_db_crnn_modile模型进行中英文混合预测(代码)实践
1. 环境搭建 参考:<PaddleOCR加载chinese_ocr_db_crnn_server模型进行中英文混合预测(命令行)实践> 2. 代码 import paddlehub as ...
- 一个关于nvarchar字段排序,中英文混合排序的问题
有一个nvachar字段,里面有很多中英文混合的纪录 当按照这个字段排序的时候,无法按照英文a-z.中文的顺序排列 晴问如何解? 另外如何设置排序规则 你看看现在是什么排序规则? select SE ...
- 12864液晶驱动源码,独创中英文混合输出
12864液晶驱动源码,独创中英文混合输出 51单片机学习笔记:ST7920控制器的12864液晶使用总结 转载于:https://www.cnblogs.com/LittleTiger/p/4724 ...
- php对中英文字符串进行截取,利用php怎么对中英文混合的字符串进行截取
利用php怎么对中英文混合的字符串进行截取 发布时间:2021-01-04 15:31:24 来源:亿速云 阅读:103 作者:Leah 利用php怎么对中英文混合的字符串进行截取?很多新手对此不是很 ...
最新文章
- CentOS下Redis安装配置小结
- 领域驱动设计DDD实战进阶第一波(十四):开发一般业务的大健康行业直销系统(订单上下文应用服务用例与接口)...
- 条款13:以对象管理资源
- 边学习新技术边工作的重要性
- java数据库编程——Insert and Retrieve Images from MySql Table Using Java
- kmeans鸢尾花分类python代码_python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)
- HDFS内副本和块的状态分析
- Python-爬虫-针对有frame框架的页面
- Lambda 表达式浅谈- 01
- python机器学习:朴素贝叶斯分类算法
- 程序员面试金典——5.1二进制插入
- python--split方法
- 对“西刺免费代理IP“爬取、测试并存入MySQL
- tcl语言读取文件一行_TCL语言笔记:TCL中的列表操作
- SharePoint 2016 Beta 2 使用体验
- django 使用mixins时报HTTP方法patch method not allow
- css切割图片是什么,两种方法实现css切割图片,只取图片中一部分
- Android基础知识 — 1.3-ARM和Thumb指令详解1
- 删除错误提交的bit 历史_软件错误的历史
- Vue实现百度下拉提示搜索