金额数字语音播报
- 作者: 一天能吃两碗饭
- 来源: 51数据库
- 2021-08-17
最近在做一个语音播报功能,开始是用speech做的。感觉效果还不错,直接可以文字转语音,然后播报出来。但是后面再测试机器上,发现播放的是英语,搜索过后发现需要语音支持。还有可能有些系统整个语音功能都可能被阉割了,所以只能另外想办法了。
另起思路:其实只有数字变化的,其他语音文字一般是固定的。那么我们可以把0-9单独录制为10个wav文件,然后把金额数字拆分为char,播放对应的文件不就ok了吗!说干就干:

先把需要的文件录制出来,具体实现代码如下:
task.run(() =>
{
decimal payamt = 123.56m;
string paystring = payamt.tostring("f2");
//播放固定的前缀语音“龙支付收款”
using (soundplayer simplesound = new soundplayer($"{application.startuppath}\\auido\\ccb.wav"))
{
simplesound.play();
//这里需要等待,具体时间为语音文件的长度
system.threading.thread.sleep(1450);
foreach (var item in paystring.toarray())
{
//播放具体数字
simplesound.soundlocation = $"{application.startuppath}\\auido\\{item}.wav";
simplesound.play();
system.threading.thread.sleep(400);
}
//播放元
simplesound.soundlocation = $"{application.startuppath}\\auido\\yuan.wav";
simplesound.play();
}
});
看起来功能已经实现了,只是听起来感觉有点迟钝的样纸,但是先这样吧。提交给测试了,后面测试过来说这个声音怎么没有单位啊,能不能加上单位呢。嗯!!!可以。
于是开始实现数字播报加单位,先去找了段数字转大字文字的功能代码参考了下,其实逻辑差不多,然后稍微改造下就ok了,思路还是一样的,先录制语音文件,需要增加单位语音文件:十百千万

然后把需要转换的数字tostring("f2"),这里不要转n2,不然会有逗号分隔的,我这里设计只支持到小于一亿元的播报。
直接上代码
public void payauido(decimal paymoney)
{
if (paymoney >= 100000000 || paymoney == 0)
{
return;
}
task.run(() =>
{
list<string> payauidourls = new list<string>();
string paystring = paymoney.tostring("f2");
//如果小于11位,则补零
if (paystring.length < 11)
{
paystring = paystring.padleft(11, '0');
}
string paywan = paystring.substring(0, 4);//取得'万'单元
string payyuan = paystring.substring(4, 4);//取得'元'单元
string paynum = paystring.substring(9, 2);//取得小数部分
//处理万
list<string> payauidourlswan = convert(paywan);
if (payauidourlswan.count > 0)
{
payauidourlswan.add($"{application.startuppath}\\auido\\wan.wav");
}
//处理元
list<string> payauidourlsyuan = convert(payyuan);
//元第一个字符是否为‘零’
if (payauidourlswan.count > 0 && payauidourlsyuan.count > 0 && paystring[4] == '0')
{
payauidourlswan.add($"{application.startuppath}\\auido\\0.wav");
}
payauidourls.addrange(payauidourlswan);
payauidourls.addrange(payauidourlsyuan);
//处理小数位
if (paynum != "00")
{
//如果只有小数,则添加‘零’
if (payauidourls.count == 0)
{
payauidourls.add($"{application.startuppath}\\auido\\0.wav");
}
payauidourls.add($"{application.startuppath}\\auido\\..wav");
payauidourls.add($"{application.startuppath}\\auido\\{paynum[0]}.wav");
//如果最后一位为‘零’,则不需要播报
if (paynum[1] != '0')
{
payauidourls.add($"{application.startuppath}\\auido\\{paynum[1]}.wav");
}
}
//添加元
payauidourls.add($"{application.startuppath}\\auido\\yuan.wav");
//播放“龙支付收款”
using (soundplayer simplesound = new soundplayer($"{application.startuppath}\\auido\\ccb.wav"))
{
simplesound.play();
system.threading.thread.sleep(1450);
foreach (string payauidourl in payauidourls)
{
//播放每个数字
simplesound.soundlocation = payauidourl;
simplesound.play();
system.threading.thread.sleep(400);
}
}
});
}
/// <summary>
/// 每四位数转换一次
/// </summary>
/// <param name="payvalue">当前转换的金额</param>
/// <returns></returns>
public list<string> convert(string payvalue)
{
list<string> payauidos = new list<string>();
//如果为四个零,则不需要播报
if (payvalue == "0000")
{
return payauidos;
}
char tmp0 = payvalue[0];
char tmp1 = payvalue[1];
char tmp2 = payvalue[2];
char tmp3 = payvalue[3];
//千位
if (tmp0 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\{tmp0}.wav");
payauidos.add($"{application.startuppath}\\auido\\qian.wav");
}
else
{
payauidos.add($"{application.startuppath}\\auido\\0.wav");
}
//百位
if (tmp1 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\{tmp1}.wav");
payauidos.add($"{application.startuppath}\\auido\\bai.wav");
}
else
{
//只添加一个零
if (tmp0 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\0.wav");
}
}
//十位
if (tmp2 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\{tmp2}.wav");
payauidos.add($"{application.startuppath}\\auido\\shi.wav");
}
else
{
//只添加一个零
if (tmp1 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\0.wav");
}
}
//个位
if (tmp3 != '0')
{
payauidos.add($"{application.startuppath}\\auido\\{tmp3}.wav");
}
//如果第一个音频为零,则去掉
if (payauidos[0].contains("0.wav"))
{
payauidos.removeat(0);
}
//如果最后一个音频为零,则去掉
if (payauidos[payauidos.count - 1].contains("0.wav"))
{
payauidos.removeat(payauidos.count - 1);
}
return payauidos;
}
输入数字,既可转换为语音播报,其实思路很简单,就是把每个数字及单位对应的语音文件连续播放出来即可。demo下载
推荐阅读
- C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)
- 团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
- 使用 MSBuild.exe 在发布模式下构建 C# 解决方案
- 当我发布 Web 应用程序时,AfterPublish 脚本不运行
- 构建时 T4 转换的产品仅在下一个构建中使用
- ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
- 新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
- 如何将条件编译符号(DefineConstants)传递给 msbuild
- MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
- NuGet 包还原找不到包,没有源
热点文章
团队城市未满足要求:MSBuildTools12.0_x86_Path 存在
0
使用 MSBuild.exe 在发布模式下构建 C# 解决方案
0
当我发布 Web 应用程序时,AfterPublish 脚本不运行
0
构建时 T4 转换的产品仅在下一个构建中使用
0
ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json
0
新的 .csproj 格式 - 如何将整个目录指定为“链接文件"到子目录?
0
如何将条件编译符号(DefineConstants)传递给 msbuild
0
MSBuild 支持 Visual Studio 2017 RTM 中的 T4 模板
0
NuGet 包还原找不到包,没有源
0
使用 C# 6.0 功能运行 TFS 构建
0
