2018-09-27 11:05:52 weixin_43112746 阅读数 7169
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

#用java调用科大讯飞的离线语音识别dll实现离线识别(JNA实现)(一)

本人接的任务,做离线语音识别,用的是科大讯飞的离线识别,java不支持离线了,所以下载了windows的离线包,用JNA进行调用。之前用的是jni,但是一直没有测试通过,本人又不会C++,研究了一个星期终究放弃。转而使用JNA,JNA使用只要导入一个jar包即可,JNA实际上是对JNI的一种封装。

【在线语音识别的实现看我的另一篇】科大讯飞 在线语音识别 音频来源为【文件】的java接入实现, 适用于初学者

说明

本人一边做一边写,记录问题和解决办法,留给自己思考和大家交流。如有不对的地方,欢迎批评指正!
【ps】现在已经做完,参考第二篇

一、注册用户,下载dll这个先略过,很简单,可以参考其他的……【待】
1、先进入讯飞开放平台,先注册【地址】https://www.xfyun.cn/
2、创建应用,记得平台选windows,因为java不支持离线
在这里插入图片描述

3、创建完成之后,在 我的应用 中
在这里插入图片描述

选择【离线命令词识别】
就完成创建了!

4、下载需要的SDK,这个SDK包含了动态库dll,静态库lib,头文件.h,以及非常重要的例子!
在这里插入图片描述
【点亮需要的功能,下载相应的SDK】
在这里插入图片描述
下载好之后,找出其中的dll文件,两个版本,上面是32位系统,下面是64位系统,本人是64位的
在这里插入图片描述

二、调用JNA
1下载jna的jar包
【JNA包下载地址】:https://download.csdn.net/download/weixin_43112746/10690193

2导入java工程中
在这里插入图片描述
jar包的位置,可以放在根目录,也可以像我一样创立一个lib文件夹来放置
然后
右键工程–properties—java Build Path----libraries—add jars
在这里插入图片描述
【找到相应的JNA包的位置,添加之后点击Apply and Close】就完成JNA包的导入
【JNA包下载地址】:https://download.csdn.net/download/weixin_43112746/10690193

没有做过的,先加载个例子试试!
在这里插入图片描述

创建一个class,一个interface,下面的是讯飞的dll文件放在根目录下
【接口】这里只测试登录的函数

package test;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;

public interface VoiceLib extends Library {
	  int MSPLogin(String usr, String pwd, String params);
	  VoiceLib instance = (VoiceLib)Native.loadLibrary("msc_x64", VoiceLib.class);//接口直接对动态库文件进行调用,
	  //省去JNI的繁琐步骤
		

}

【类】
package test;

import com.sun.jna.Native;

public class Voice {
		public static void main(String[] args) {
		String usr=null;
		String pwd=null;
		String params="appid=5ba4bc08";//这里填写自己的appid,从讯飞的我的应用里面粘贴过来
		int a;
		a=VoiceLib.instance.MSPLogin(usr, pwd, params);//调用接口的方法传参数
		System.out.println(“a=+a);
		
		
	}
}




输出结果a=0
很明显测试成功了!
能够继续往下写了。

又遇到问题,参数的转换!
普通的倒是还好,转换关系如下:
在这里插入图片描述
来源:https://github.com/java-native-access/jna/blob/master/www/Mappings.md
可是问题来了,讯飞中有指针,句柄,回调函数等等各种乱七八糟的参数,这可怎么转换?头顶一直乌鸦飞过……

三、参数的转换(难点)
登录做完了,再做构建语法,其中用到的函数是

int MSPAPI QISRBuildGrammar(const char *grammarType, const char *grammarContent, unsigned int grammarLength,
 const char *params, GrammarCallBack callback, void *userData);

除了无符号int那个,其他都没有!又一只乌鸦飞过……
竟然还有语法回调函数!这是什么!又一只乌鸦飞过……
查一下回调函数
【百度】这是个链接哈

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

找个资源帖参考下:
https://blog.csdn.net/l527719041/article/details/77461328

哦!原来可以这么操作!

先把const char *解决,这是要转换成String 【待】

再来解决回调函数的参数问题!
【先做这么多,下回分解】
第二篇的链接:手把手的操作——用java调用科大讯飞的离线语音识别dll实现离线识别(JNA实现)(二)

2017-04-11 20:47:52 ShareUs 阅读数 7514
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

  语音识别,语音合成语音技术主要分两块:一块是语音转文字,即语音识别;另一块是文字转语音,即语音合成。
  语音相关技术研发 语音合成技术整体解决方案。一系列语音技术的相关专利,包括文本处理、韵律预测、声学模型、拼接系统、模型自适应、神经网络、情感合成等多个方面。
  应用场景:在线语音合成、离线语音合成系统场景- 读故事,小说频道,读新闻(新闻中的语音播报)。声学行业.。
智能音箱大战全面开火- http://blog.csdn.net/dqcfkyqdxym3f8rb0/article/details/78574066

  Librispeech是当前衡量语音识别技术的最权威主流的开源数据集。错词率(Worderrorrate,WER)是衡量语音识别技术水平的核心指标。近日,云从科技在Librispeech数据集上将错词率(Worderrorrate,WER)降到了2.97%,较之前提升了25%。超过阿里、百度、约翰霍普金斯大学等企业及高校,大幅刷新原先记录。

  tts识别,合成,播放。
-- 支付宝的语音收款方案为:文字已经录好在文件中

Android支付宝商家收款语音播报(无SDK)- https://www.jianshu.com/p/62e6382c610b

支付宝商家语音播报- https://github.com/YzyCoding/PushVoiceBroadcast

-- 变声:萝莉/大叔/卖萌/搞笑等

Android QQ变声特效例子- https://github.com/huanglinqing123/ChangeVoice/tree/master 
 在QQ中我们使用到的一个功能就是变声,QQ是使用FMOD实现的,那么同样的我们也使用FMOD让自己的应用可以变音。
 fmod Ex 声音系统是为游戏开发者准备的革命性音频引擎,链接:https://pan.baidu.com/s/1TW3ctQd0o5bOVCx5gKL0hA 密码:x2o4 。 fmod声音系统是为游戏开发者准备的革命性音频引擎,如今采用了fmod作为音频引擎的游戏包括Far Cry(孤岛惊魂)、Tom Clancy's Ghost Recon(幽灵行动),甚至著名的World Of Warcraft(魔兽争霸)。
仿QQ语音变声功能实现- https://github.com/CN-ZPH/MySound https://github.com/fsrmeng/VoiceChange https://github.com/Android-LiuHuan/MyVoice

> 语音识别(ASR)与语音合成服务(TTS)
  语音识别(ASR)、语音合成(TTS)、语义理解(NLP)等技术。
语音识别ASR技术通识- https://blog.csdn.net/ZLJ925/article/details/79045034
MRCP协议-提供语音识别(ASR)与语音合成服务(TTS)-https://blog.51cto.com/chenwen/1434915

  语音识别技术(ASR)——将人说话的语音信号转换为可被计算机识别的文字信息,从而识别说话人的语音指令以及文字内容的技术。
  语音合成技术(TTS)——将文字信息转变为语音数据,以语音的方式播放出来的技术。
  TTS,英文全称是TextToSpeech,即文语转换,又称为计算机语音合成,它的过程和ASR刚好相反,是把计算机中任意出现的文字转换成自然流畅的语音输出。一般认为,语音合成系统包括三个主要的组成部分:文本分析模块、韵律生成模块和声学模块。目前,TTS的技术已经可以达到商业化的地步。

-- MRCP
   媒体资源控制协议(Media Resource Control Protocol,MRCP)是由Cisco、Nuance等公司联合开发的网络协议,该协议由IETF作为Internet草案发布(draft-shanmugham-mrcp-07)。该协议为那些需要进行语音处理的客户端提供了一种通过网络来控制媒体处理资源(如ASR、TTS引擎等)的机制。该协议在设计之初就考虑了可以在将来得到扩展以支持声纹鉴别和身份识别(Speaker Identification/Speaker Verification)等功能。 
  媒体资源控制协议(Media Resource Control Protocol, MRCP)是一种通讯协议,用于语音服务器向客户端提供各种语音服务(如语音识别和语音合成)。
  MRCP并不定义会话连接,不关心服务器与客户端是如何连接的,MRCP的消息通常是承载于其它协议之上,如RTSP,SIP等。
 MRCP消息使用类似于HTTP等许多Internet协议一样的文本格式,每个消息包括三部分:首行,消息头,消息体。首行表明消息类型及返回码等信息。消息头包括了若干行内容,每一行都形如 "字段名:数值"。消息体包括了消息的详细内容,长度在消息头中指定。
 随着MRCP协议的不断推广与应用,各语音技术厂商在实践与部署过程中碰到了各种各样的问题。为此,IESG(The Internet Engineering Steering Group)于2002年特许成立了Speechsc工作组,专门负责起草更加完善高效的支持分布式语音资源处理的开放协议。在Speechsc工作组的努力下,改进后的MRCPv2(draft-ietf-speechsc-mrcpv2-09)很快应运而生了。MRCPv2的消息格式和资源状态机等都建立在MRCP协议版本1的基础之上,它完全兼容W3C的SSML、SRGS、NLSML标准。与MRCPv1不同的是MRCPv2消息不再依赖RTSP作为载体,而是作为独立的消息进行传输,但是它仍依赖于会话管理协议,如SIP(Session Initiation Protocol)协议,来在客户端与服务器端之间建立控制会话。 
 MRCP设计的特定目标很明确,就是为那些采用不同厂商的ASR和TTS产品来构建IVR或消息类应用的开发商提供便利。

-- 主流语音技术
目前国外几乎所有的主流语音技术供应商都已经宣布推出基于MRCPv1的产品:
 ● 语音资源供应商:Acapela、BBN、IBM、Loquendo、Nuance(ScanSoft)、Rhetorical、Telisma等;
 ● 板卡技术供应商:Intel、NMS、Aculab等;
 ● 语音技术应用集成商:Cisco、Nortel、Lucent、HP、Edify、Genesys、Intervoice、SER、Unisys、Convedia等。 
  市场上有很多比较成熟的语音ASR和TTS产品,而且他们大多数都支持二次开发,如微软的Speech Application SDK(SASDK)、IBM的Dutty++等。他们能识别(生成)英语、日语和中文等不同国家的语言,Dutty++甚至能够识别某些地区的方言,如广东的方言-粤语。
  科大讯飞、百度语音、捷通华声、云知声等。阿里云语音识别。
  微软SAPI将ASR和TTS功能集成在同一个语音引擎中,TTS可以将文本和文件合成为语音,ASR则是将人的声音信号转换为可读的文本或文件。

  语音识别(Automatic Speech Recognition),一般简称ASR;是将声音转化为文字的过程,相当于人类的耳朵。
  语音识别原理流程:“输入——编码——解码——输出”
  语音识别,大体可分为“传统”识别方式与“端到端”识别方式,其主要差异就体现在声学模型上。“传统”方式的声学模型一般采用隐马尔可夫模型(HMM),而“端到端”方式一般采用深度神经网络(DNN)。
  远场语音识别,简称远场识别,口语中可更简化为“远场”。下面主要说3个概念:语音激活检测、语音唤醒、以及麦克风阵列。

 iphone 6s 语音激活的低功耗芯片.按麦克风个数分:单麦、双麦、多麦 .
 车内语音识别的难点很多,除了多人说话的干扰,还有胎噪、风噪,以及经常处于离线情况。 

  语音识别系统的性能大致取决于以下4类因素:1. 识别词汇表的大小和语音的复杂性;2. 语音信号的质量;3. 单个说话人还是多说话人;4. 硬件。

  媒体采集设备主要用来采集各种语音信号,如对普通的电信网,就是PCM a律信号的采集;而对VOIP应用,采集的信号可能有很多种,包括G.711/G.723/G.729等各种语音格式。同时,该设备还需要具备一定的媒体转换能力,能将各种媒体流转换为ASR能够识别的语音格式。
  语音识别是一个多学科交叉的领域,它与声学、语音学、语言学、数字信号处理理论、信息论、计算机科学等众多学科紧密相连。
  TTS的技术实现方法,主要有2种:“拼接法”和“参数法”。

  语音识别主要识别框架:基于模式匹配的动态时间规整法(DTW)和基于统计模型的隐马尔可夫模型法(HMM)。

https://img-blog.csdnimg.cn/20190511215006499.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1NoYXJlVXM=,size_16,color_FFFFFF,t_70

> 汉字转拼音(ASCII码映射等)
Android 汉字转拼音的多种实现方式- http://blog.csdn.net/zhuwentao2150/article/details/70230341?ref=myread
利用Android源码,轻松实现汉字转拼音功能- http://blog.csdn.net/D_clock/article/details/69890954

HanziToPinyin(汉字转拼音)- https://gist.github.com/D-clock/7a6e33f42c0177439a49d85b73f1e600

jpinyin- https://github.com/stuxuhai/jpinyin

 -- Android平台上将汉字转换成为拼音已经有一些开源的第三方实现方案,如pinyin4j和TinyPinyin
TinyPinyin:https://github.com/promeG/TinyPinyin
   建立一个大的对照表(比如用关联容器Map),同时一个汉字可能有多个发音,也就是说Map这样的容器时不行的,因为其<key,value>必须是一一对应的。在C++中可以用STL里面的multimap来解决这个问题,但Java中没有类似multimap这样的东西,除非自己实现一个。pinyin4j(将汉字转化为拼音):https://sourceforge.net/projects/pinyin4j .
Pinyin4j(http://pinyin4j.sourceforge.net/)就是为了解决类似这样的问题的。它是sourceforge.net上的一个开源项目,功能非常强大:
 1.支持同一汉字有多个发音
 2.还支持拼音的格式化输出,比如第几声之类的,
 3.同时支持简体中文、繁体中文转换为拼音…使用起来也非常简单。> TTS

-- 汉语拼音开源:tinypinyin, pinyin4j
城市demo--  http://github.com/18722527635/CityDemo

> 语音识别引擎
Android中文语音合成(TTS)各家引擎对比- http://blog.csdn.net/yao_guet/article/details/7231489/
Android 文本转语音TextToSpeech (TTS)- http://blog.csdn.net/zhoumushui/article/details/50496661
【Android语音合成TTS】国内主流引擎对比- http://blog.csdn.net/fengyuzhengfan/article/details/45052823
-- 五款免费开源的语音识别工具- https://blog.csdn.net/godloveyuxu/article/details/77416017
  直到几年之前,最先进的语音技术方案大多都是以语音为基础的(phonetic-based),包括发音模型(Pronunciation models),声学模型(Acoustic Modelling)和语言模型(Language Model)等。通常情况下,这些模型大多都是以隐马尔可夫模型(HMM)和 N-gram 模型为核心的。
  五款基于 HMM 和 N-gram 模型的语音识别工具:CMU Sphinx,Kaldi,HTK,Julius 和 ISIP。它们都是开源世界的顶级项目,与 Dragon 和 Cortana 等商业语音识别工具不同
  基于 Julius 的语音识别样例- https://github.com/julius-speech/dictation-kit 
  18 个开源翻译工具帮助你的项目本地化- https://blog.csdn.net/hj7jay/article/details/74171368

-- 常见的语音sdk主要有:科大讯飞、百度语音、捷通华声、云知声等 手说TTS;讯飞的语音识别/百度语音识别
 Google Cloud API,百度,科大讯飞的都是初期免费,量大收费.
 JAVA SPEECH 和 SPHINX 等实现方式, 语音引擎(TTS引擎) IBM以前那个语音识别;
 到google上去搜索iris.TTS,就是语音转文本, 其中涉及的语音采样(本地,方言,外语等等)识别技术,在国内有科大讯飞和捷通比较有名,在国外有一个叫luance公司比较有名 。
> Android中文语音合成引擎的设计与实现,及在Android上应用

Google的TTS对中文不支持,支持英文。
android自带的类,从文本中合成语音,用于立即播放或创建一个声音文件.中文的话,需要手机系统有安装中文引擎吧
https://developer.android.google.cn/reference/android/speech/tts/TextToSpeech.html
https://github.com/SolveBugs/Utils
TTS文字转语音并朗读- https://github.com/codestravel/CT_Android_demos/tree/master/CT_Text2SpeechDemo
android 文字转语音 tts 实现 支持中文 - http://download.csdn.net/download/kingda008/7570591
TTS_library_stub_3.0_market.jar-  http://download.csdn.net/download/seamless_yang/6996789
Android TTS说中文- http://blog.csdn.net/true100/article/details/50864247
开源google框架提供了中文TTS功能- http://code.google.com/p/eyes-free/

2016-07-06 16:37:35 victor_barnett 阅读数 3498
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

        用了半天时间弄明白了在iOS上如何配置语音识别功能,然后用半天时间写了一个demo,公司坑爹的是不用科大飞讯的语音识别,而使用的是OpenEars,用google查了一下最新的介绍文章是2013年的,OpenEars是一款国外比较主流的语音识别的第三方框架,全是英文文档(吐槽一下,做开发必须要学好英语啊).

1.什么是OpenEars?

        OpenEars是面向iOS平台的一个离线的语音识别和text-to-speech(文字语音转换)开发工具包.OpenEars主要是针对英语,也支持中文的语言包,但是我感觉它的识别性不是太好.最重要的是,这是一款免费的工具包,除了基本的免费功能,它还提供了可以用来扩展基本功能的付费插件.今天主要介绍的是它的免费功能,即简单的语音识别功能.


        当前OpenEars的最新版本为2.5,下载地址为http://www.politepix.com/wp-content/uploads/OpenEarsDistribution.tar.bz2


2.详细配置OpenEars的步骤

(1)点击上方链接下载OpenEars的扩展包,打击打开扩展包,里面有一个Framework的文件夹,将这个文件拖进你的工程文件中.然后检查这个文件的路径(正常情况下Xcode会为你自动添加好文件的路径),点击你的工程文件,然后点击Build Settings,在搜索输入框输入Framework Search Paths,右键点击刚刚添加的Framework文件夹,然后show in finder即可查看文件的路径,核对两个路径是否正确.不正确或者不存在,手动添加即可.见图


核对检查好路径之后,为了添加二进制文件的存储,需要将Build Settings里的Deployment Postprocessing设置为YES.然后添加AudioToolbox库和AVFoundation库到你的项目里边.



(2)在你需要进行语音识别的.m文件下引入头文件,需引入头文件如下:


在你需要进行语音识别的.h文件下引入头文件,需引入头文件如下:


然后跟你需要实现语音识别的文件下引入协议(绿色<>部分为需要引入的协议),例如


并将OEEventsObserver属性添加到您的其他类属性(OEEventsObserver必须您的类的属性,否则它不会工作):



然后在viewDidLoad或者你需要的地方进行初始化观察者并签订协议:



下一步是创建你需要使用到的语音类文件,这决定你将使用什么语言进行识别,在viewDidLoad或者其他地方均可,具体实现如下:


其中的words是你创建的需要识别的单词.

最后在你需要开启语音识别的地方添加如下方法,开启语音识别:



其中你注册的观察者签订的协议方法如下所示



包含中文和英文声学模型的demo地址:Demo地址



2018-04-17 11:06:48 little_soybean 阅读数 255
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波

前不久项目中用到了语音识别技术,因此就研究了一下语音识别技术在项目中的集成。由于我是在公司的设备上运行的,所以没有截图,为了直观方便的看一下效果,所以就在网上找了两张和我的项目运行后差不多的图片。

这里写图片描述

市场上的语音技术应用最广泛的有两种,一种是百度的语音识别,一种是科大讯飞的语音识别。两者之间的不同之处在于,前者是完全免费的,后者在离线状态识别语音是收费的。今天先记录一下科大讯飞在线的语音识别,等有机会在记录一下百度的语音识别。

首先需要在科大讯飞的开放平台上申请一个账号,申请的过程就不再描述。申请成功以后,平台会发放一个APPID号。这个ID号留待使用。 然后平台会让你创建一个应用,这时候你把自己的应用信息填好以后,选择SDK下载。

当SDK下载完以后,会得到一个ZIP压缩包,解开这个压缩包,会看到如下的文件:

这里写图片描述

其中assets目录里是资源文件,主要是语音识别的弹出框图片,可以原封不动拷过来。如果只是单纯的识别,还需要拷贝两个文件,一个是libs下的armeabi文件夹,一个是libs下的Msc.jar。拷贝完以后,放到项目的libs文件夹下。

准备工作完成以后,就可以进行代码的编写了,一般是在点击某个按钮以后,进入语音识别的情景。在这里假设点击了某个按钮的场景

package com.szh.speechdemo.activity;

import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.szh.speechdemo.R;
import com.szh.speechdemo.model.DictationResult;

public class MainActivity extends Activity {

    public static final String TAG = "MainActivity";
    private EditText etText;
    private Button btn_yysb;
    private Button btn_save;
    private RecognizerDialog iatDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        // 初始化即创建语音配置对象,只有初始化后才可以使用MSC的各项服务
        // 此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请使用参数:SpeechConstant.APPID
        // +"=12345678," + SpeechConstant.FORCE_LOGIN +"=true"。
        setContentView(R.layout.activity_main);

        btn_yysb = (Button) findViewById(R.id.btn_yysb);
        etText = (EditText)findViewById(R.id.etText);
        btn_save = (Button) findViewById(R.id.btn_save);

        btn_save.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                SpeechUtility.getUtility().destroy();  
            }
        });



        btn_yysb.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // ①语音配置对象初始化
                SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=5a587636");
                // ②初始化有交互动画的语音识别器
                iatDialog = new RecognizerDialog(MainActivity.this, mInitListener);
                // ③设置监听,实现听写结果的回调
                iatDialog.setListener(new RecognizerDialogListener() {
                    String resultJson = "[";// 放置在外边做类的变量则报错,会造成json格式不对(?)

                    @Override
                    public void onResult(RecognizerResult recognizerResult, boolean isLast) {
                        System.out .println("-----------------   onResult   -----------------");
                        if (!isLast) {
                            resultJson += recognizerResult.getResultString() + ",";
                        } else {
                            resultJson += recognizerResult.getResultString() + "]";
                        }

                        if (isLast) {
                            // 解析语音识别后返回的json格式的结果
                            Gson gson = new Gson();
                            List<DictationResult> resultList = gson.fromJson(
                                    resultJson,
                                    new TypeToken<List<DictationResult>>() {
                                    }.getType());
                            String result = "";
                            for (int i = 0; i < resultList.size() - 1; i++) {
                                result += resultList.get(i).toString();
                            }
                            etText.setText(result);
                            // 获取焦点
                            etText.requestFocus();
                            // 将光标定位到文字最后,以便修改
                            etText.setSelection(result.length());
                        }
                    }

                    @Override
                    public void onError(SpeechError speechError) {
                        // 自动生成的方法存根
                        speechError.getPlainDescription(true);
                    }
                });
                // 开始听写,需将sdk中的assets文件下的文件夹拷入项目的assets文件夹下(没有的话自己新建)
                iatDialog.show();
            }
        });
    }

    // 3.开始听写 mIat.startListening(mRecoListener);
    // 听写监听器
    private InitListener mInitListener = new InitListener() {
        @Override
        public void onInit(int code) {
            Log.d(TAG, "SpeechRecognizer init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                Toast.makeText(MainActivity.this, "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();
            }
        }
    };
}

当语音转化成文字的时候,我们还需要用到Gson进行转换成bean进行封装,bean结构如下:

package com.szh.speechdemo.model;

import java.util.List;

public class DictationResult {

    private String sn;
    private String ls;
    private String bg;
    private String ed;
    private List<Words> ws;

    public static class Words {
        private String bg;
        private List<Cw> cw;

        public static class Cw {
            private String w;
            private String sc;

            public String getW() {
                return w;
            }

            public void setW(String w) {
                this.w = w;
            }

            public String getSc() {
                return sc;
            }

            public void setSc(String sc) {
                this.sc = sc;
            }

            @Override
            public String toString() {
                return w;
            }
        }

        public String getBg() {
            return bg;
        }

        public void setBg(String bg) {
            this.bg = bg;
        }

        public List<Cw> getCw() {
            return cw;
        }

        public void setCw(List<Cw> cw) {
            this.cw = cw;
        }

        @Override
        public String toString() {
            String result = "";
            for (Cw cwTmp : cw) {
                result += cwTmp.toString();
            }
            return result;
        }
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public String getLs() {
        return ls;
    }

    public void setLs(String ls) {
        this.ls = ls;
    }

    public String getBg() {
        return bg;
    }

    public void setBg(String bg) {
        this.bg = bg;
    }

    public String getEd() {
        return ed;
    }

    public void setEd(String ed) {
        this.ed = ed;
    }

    public List<Words> getWs() {
        return ws;
    }

    public void setWs(List<Words> ws) {
        this.ws = ws;
    }

    @Override
    public String toString() {
        String result = "";
        for (Words wsTmp : ws) {
            result += wsTmp.toString();
        }
        return result;
    }
}

在这里有些细节还需要注意:
第一点,SpeechUtility.getUtility().destroy();这句代码是注销语音的,如果语音已经被注销掉,但是在初始化的时候只初始化了一次,下次再注销的时候就会报错。
第二点,如果是在activity中,onCreate方法中如果不回调super.onCreate(savedInstanceState)方法,会出现闪退现象。

我把项目中用到的资源文件和jar包放上链接,有需要的可以自行下载。下载积分本来想设置成0积分,不过好像最少就是2,无法设置不要积分下载。如果嫌麻烦就从这下载,或者在网上搜别的也行。
链接如下:https://download.csdn.net/download/little_soybean/10354424

2018-08-21 14:05:18 mm_name_zhang 阅读数 2554
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5905 人正在学习 去看看 杨波
/***
 * 
 * 离线、云端语音识别类
 * 
 */
public class AsrDemo extends Activity implements OnClickListener{
   private static String TAG = AsrDemo.class.getSimpleName();
   // 语音识别对象
   private SpeechRecognizer mAsr;
   private Toast mToast;  
   // 缓存
   private SharedPreferences mSharedPreferences;
   // 本地语法文件
   private String mLocalGrammar = null;
   // 本地词典
   private String mLocalLexicon = null;
   // 云端语法文件
   private String mCloudGrammar = null;
   // 本地语法构建路径    
   private String grmPath = Environment.getExternalStorageDirectory()
                        .getAbsolutePath() + "/msc/test";
   // 返回结果格式,支持:xml,json
   private String mResultType = "json";
   
   private  final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id";
   private  final String GRAMMAR_TYPE_ABNF = "abnf";
   private  final String GRAMMAR_TYPE_BNF = "bnf";

   private String mEngineType = "cloud";
    private TtsUtils ttsUtils;
    private TtsOffUtil ttsOffUtil;

    @SuppressLint("ShowToast")
   public void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      this.requestWindowFeature(Window.FEATURE_NO_TITLE);
      setContentView(R.layout.isrdemo);
      initLayout();
        ttsUtils = new TtsUtils();
        ttsOffUtil = new TtsOffUtil(this);

        // 初始化识别对象
      mAsr = SpeechRecognizer.createRecognizer(this, mInitListener);    

      // 初始化语法、命令词
      mLocalLexicon = "张海羊\n刘婧\n王锋\n";
      mLocalGrammar = FucUtil.readFile(this,"call.bnf", "utf-8");
      mCloudGrammar = FucUtil.readFile(this,"grammar_sample.abnf","utf-8");
      
      // 获取联系人,本地更新词典时使用
      ContactManager mgr = ContactManager.createManager(AsrDemo.this, mContactListener);
      mgr.asyncQueryAllContactsName();
      mSharedPreferences = getSharedPreferences(getPackageName(),    MODE_PRIVATE);
      mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT);   
      
   }
   
   /**
    * 初始化Layout。
    */
   private void initLayout(){
      findViewById(R.id.isr_recognize).setOnClickListener(this);
      
      findViewById(R.id.isr_grammar).setOnClickListener(this);
      findViewById(R.id.isr_lexcion).setOnClickListener(this);
      
      findViewById(R.id.isr_stop).setOnClickListener(this);
      findViewById(R.id.isr_cancel).setOnClickListener(this);

      //选择云端or本地
      RadioGroup group = (RadioGroup)this.findViewById(R.id.radioGroup);
      group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
         @Override
         public void onCheckedChanged(RadioGroup group, int checkedId) {
            if(checkedId == R.id.radioCloud)
            {
               ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
               findViewById(R.id.isr_lexcion).setEnabled(false);
               mEngineType = SpeechConstant.TYPE_CLOUD;
            }else if(checkedId == R.id.radioLocal)
            {
               ((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
               findViewById(R.id.isr_lexcion).setEnabled(true);
               mEngineType =  SpeechConstant.TYPE_LOCAL;
            }
         }
      });
   }
    
   
   String mContent;// 语法、词典临时变量
    int ret = 0;// 函数调用返回值
   @Override
   public void onClick(View view) {      
      if( null == mAsr ){
         // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
         this.showTip( "创建对象失败,请确认 libmsc.so 放置正确,\n 且有调用 createUtility 进行初始化" );
         return;
      }
      
      if(null == mEngineType) {
         showTip("请先选择识别引擎类型");
         return;
      }  
      switch(view.getId())
      {
         case R.id.isr_grammar:
            showTip("上传预设关键词/语法文件");
            // 本地-构建语法文件,生成语法id
            if (mEngineType.equals(SpeechConstant.TYPE_LOCAL)) {
               ((EditText)findViewById(R.id.isr_text)).setText(mLocalGrammar);
               mContent = new String(mLocalGrammar);
               mAsr.setParameter(SpeechConstant.PARAMS, null);
               // 设置文本编码格式
               mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
               // 设置引擎类型
               mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
               // 设置语法构建路径
               mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
               //使用8k音频的时候请解开注释
//             mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
               // 设置资源路径
               mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
               ret = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, grammarListener);
               if(ret != ErrorCode.SUCCESS){
                  showTip("语法构建失败,错误码:" + ret);
               }
            }
            // 在线-构建语法文件,生成语法id
            else { 
               ((EditText)findViewById(R.id.isr_text)).setText(mCloudGrammar);
               mContent = new String(mCloudGrammar);
               // 指定引擎类型
               mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
               // 设置文本编码格式
               mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
                ret = mAsr.buildGrammar(GRAMMAR_TYPE_ABNF, mContent, grammarListener);
               if(ret != ErrorCode.SUCCESS)
                  showTip("语法构建失败,错误码:" + ret);
            }
            break;
         // 本地-更新词典
         case R.id.isr_lexcion: 
            ((EditText)findViewById(R.id.isr_text)).setText(mLocalLexicon);
            mContent = new String(mLocalLexicon);
            mAsr.setParameter(SpeechConstant.PARAMS, null);
            // 设置引擎类型
            mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
            // 设置资源路径
            mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
            //使用8k音频的时候请解开注释
//          mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
            // 设置语法构建路径
            mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
            // 设置语法名称
            mAsr.setParameter(SpeechConstant.GRAMMAR_LIST, "call");
            // 设置文本编码格式
            mAsr.setParameter(SpeechConstant.TEXT_ENCODING,"utf-8");
            ret = mAsr.updateLexicon("contact", mContent, lexiconListener);
            if(ret != ErrorCode.SUCCESS){
               showTip("更新词典失败,错误码:" + ret);
            }
            break;
         // 开始识别
         case R.id.isr_recognize:
            ((EditText)findViewById(R.id.isr_text)).setText(null);// 清空显示内容
            // 设置参数
            if (!setParam()) {
               showTip("请先构建语法。");
               return;
            };
            
            ret = mAsr.startListening(mRecognizerListener);
            if (ret != ErrorCode.SUCCESS) {
               showTip("识别失败,错误码: " + ret);   
            }
            break;
         // 停止识别
         case R.id.isr_stop:
            mAsr.stopListening();
            showTip("停止识别");
            break;
         // 取消识别
         case R.id.isr_cancel:
            mAsr.cancel();
            showTip("取消识别");
            break;
      }
   }
   
   /**
     * 初始化监听器。
     */
    private InitListener mInitListener = new InitListener() {

      @Override
      public void onInit(int code) {
         Log.d(TAG, "SpeechRecognizer init() code = " + code);
         if (code != ErrorCode.SUCCESS) {
              showTip("初始化失败,错误码:"+code);
           }
      }
    };
       
   /**
     * 更新词典监听器。
     */
   private LexiconListener lexiconListener = new LexiconListener() {
      @Override
      public void onLexiconUpdated(String lexiconId, SpeechError error) {
         if(error == null){
            showTip("词典更新成功");
         }else{
            showTip("词典更新失败,错误码:"+error.getErrorCode());
         }
      }
   };
   
   /**
     * 构建语法监听器。
     */
   private GrammarListener grammarListener = new GrammarListener() {
      @Override
      public void onBuildFinish(String grammarId, SpeechError error) {
         if(error == null){
            if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {
               Editor editor = mSharedPreferences.edit();
               if(!TextUtils.isEmpty(grammarId))
                  editor.putString(KEY_GRAMMAR_ABNF_ID, grammarId);
               editor.commit();
            }
            showTip("语法构建成功:" + grammarId);
         }else{
            showTip("语法构建失败,错误码:" + error.getErrorCode());
         }        
      }
   };
   /**
    * 获取联系人监听器。
    */
   private ContactListener mContactListener = new ContactListener() {
      @Override
      public void onContactQueryFinish(String contactInfos, boolean changeFlag) {
         //获取联系人
         mLocalLexicon = contactInfos;
      }     
   };
   /**
     * 识别监听器。
     */
    private RecognizerListener mRecognizerListener = new RecognizerListener() {
        /**
         * 返回的声音结果
         * @param volume
         * @param data
         */
        @Override
        public void onVolumeChanged(int volume, byte[] data) {
           showTip("当前正在说话,音量大小:" + volume);
           Log.d(TAG, "返回音频数据:"+data.length);
        }

        /**
         * 语音返回结果
         * @param result
         * @param isLast
         */
      @Override
      public void onResult(final RecognizerResult result, boolean isLast) {
         if (null != result && !TextUtils.isEmpty(result.getResultString())) {
            Log.d(TAG, "recognizer result:" + result.getResultString());
            String text = "";
            if (mResultType.equals("json")) {
                    String resultString = result.getResultString();
                    Log.d("HHA",resultString);
                     Gson g=new Gson();
                    MessageBaen messageBaen = g.fromJson(resultString, MessageBaen.class);
                    List<MessageBaen.WsBean> ws = messageBaen.getWs();
                    StringBuffer bb=new StringBuffer();
                    for (MessageBaen.WsBean w : ws) {
                        List<MessageBaen.WsBean.CwBean> cw = w.getCw();
                        for (int i = 0; i < cw.size(); i++) {
                            String w1 = cw.get(i).getW();
                            bb.append(w1);
                        }
                    }
                    Log.d("HHA=",bb.toString());
                    text = JsonParser.parseGrammarResult(result.getResultString(), mEngineType);
                    //ttsUtils.ff(bb.toString(),AsrDemo.this);//在线语音合成
                    ttsOffUtil.setData(bb.toString());//离线语音合成
            } else if (mResultType.equals("xml")) {
               text = XmlParser.parseNluResult(result.getResultString());
            }
            // 显示
            ((EditText) findViewById(R.id.isr_text)).setText(text);
         } else {
            Log.d(TAG, "recognizer result : null");
         }
      }

        /***
         * 结束说话
         */
        @Override
        public void onEndOfSpeech() {
           // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入          
         showTip("结束说话");
        }


        /***
         * 开始说话
         */
        @Override
        public void onBeginOfSpeech() {
           // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
           showTip("开始说话");
        }

        /***
         * 错无
         */
      @Override
      public void onError(SpeechError error) {
         showTip("onError Code:"    + error.getErrorCode());
      }

      @Override
      public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
         // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
         // 若使用本地能力,会话id为null
         // if (SpeechEvent.EVENT_SESSION_ID == eventType) {
         //    String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
         //    Log.d(TAG, "session id =" + sid);
         // }
      }

    };
    
   

   private void showTip(final String str) {
      runOnUiThread(new Runnable() {
         @Override
         public void run() {
            mToast.setText(str);
            mToast.show();
         }
      });
   }

   /**
    * 参数设置
    * @param
    * @return 
    */
   public boolean setParam(){
      boolean result = false;
      // 清空参数
      mAsr.setParameter(SpeechConstant.PARAMS, null);
      // 设置识别引擎
      mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
      if("cloud".equalsIgnoreCase(mEngineType))
      {
         String grammarId = mSharedPreferences.getString(KEY_GRAMMAR_ABNF_ID, null);
         if(TextUtils.isEmpty(grammarId))
         {
            result =  false;
         }else {
            // 设置返回结果格式
            mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
            // 设置云端识别使用的语法id
            mAsr.setParameter(SpeechConstant.CLOUD_GRAMMAR, grammarId);
            result =  true;
         }
      }
      else
      {
         // 设置本地识别资源
         mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath());
         // 设置语法构建路径
         mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath);
         // 设置返回结果格式
         mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType);
         // 设置本地识别使用语法id
         mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call");
         // 设置识别的门限值
         mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30");
         // 使用8k音频的时候请解开注释
//       mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000");
         result = true;
      }
      
      // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
      // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
      mAsr.setParameter(SpeechConstant.AUDIO_FORMAT,"wav");
      mAsr.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/asr.wav");
      return result;
   }
   
   //获取识别资源路径
   private String getResourcePath(){
      StringBuffer tempBuffer = new StringBuffer();
      //识别通用资源
      tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "asr/common.jet"));
      //识别8k资源-使用8k的时候请解开注释
//    tempBuffer.append(";");
//    tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "asr/common_8k.jet"));
      return tempBuffer.toString();
   }
   
   @Override
   protected void onDestroy() {
      super.onDestroy();
      if( null != mAsr ){
         // 退出时释放连接
         mAsr.cancel();
         mAsr.destroy();
      }
   }
   
}



/**
 * 离线
 * 语音合成类
 * Created by admin on 2018/8/21.
 */
public class TtsOffUtil {
    public static final String TAG = "tttt";
    private final Context context;
    private SpeechSynthesizer mTts;
    private Toast mToast;
    private int mPercentForPlaying;
    // 默认本地发音人
    public static String voicerLocal="xiaoyan";
    // 引擎类型
    private String mEngineType =  SpeechConstant.TYPE_LOCAL;
    private SharedPreferences mSharedPreferences;


    public TtsOffUtil(Context context){
       this.context=context;
    }

    /***
     *   接受值合成语音
     * @param text
     */
    public void setData(String text){
        setParam();
        Log.d("TTTT",text);
        Toast.makeText(context,"TtsOffUtil="+text,Toast.LENGTH_SHORT).show();
        ff(text, context);
    }


    /**
     * 参数设置
     * @return
     */
    private void setParam(){
        mSharedPreferences = context.getSharedPreferences(TtsSettings.PREFER_NAME, Activity.MODE_PRIVATE);
        mToast = Toast.makeText(context, "", Toast.LENGTH_SHORT);
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(context, mTtsInitListener);
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        //设置合成
        if(mEngineType.equals(SpeechConstant.TYPE_CLOUD))
        {
            //设置使用云端引擎
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
            //设置发音人
            mTts.setParameter(SpeechConstant.VOICE_NAME,voicerCloud);
        }else {
            //设置使用本地引擎
            mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
            //设置发音人资源路径
            mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
            //设置发音人
            mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);
        }
        //设置合成语速
        mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
        //设置合成音调
        mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
        //设置合成音量
        mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
        //设置播放器音频流类型
        mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));

        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
    }

    //获取发音人资源路径
    private String getResourcePath(){
        StringBuffer tempBuffer = new StringBuffer();
        //合成通用资源
        tempBuffer.append(ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "tts/common.jet"));
        tempBuffer.append(";");
        //发音人资源
        tempBuffer.append(ResourceUtil.generateResourcePath(context, ResourceUtil.RESOURCE_TYPE.assets, "tts/"+this.voicerLocal+".jet"));
        return tempBuffer.toString();
    }



    /**
     * 初始化监听。
     */
    private InitListener mTtsInitListener = new InitListener() {


        @Override
        public void onInit(int code) {
            Log.d(TAG, "InitListener init() code = " + code);
            if (code != ErrorCode.SUCCESS) {
                showTip("初始化失败,错误码:"+code);
            } else {
                // 初始化成功,之后可以调用startSpeaking方法
                // 注:有的开发者在onCreate方法中创建完合成对象之后马上就调用startSpeaking进行合成,
                // 正确的做法是将onCreate中的startSpeaking调用移至这里
            }
        }
    };

    /**
     * 合成回调监听。
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {

        private int mPercentForBuffering;

        @Override
        public void onSpeakBegin() {
            showTip("开始播放");
        }

        @Override
        public void onSpeakPaused() {
            showTip("暂停播放");
        }

        @Override
        public void onSpeakResumed() {
            showTip("继续播放");
        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos,
                                     String info) {
            // 合成进度
             mPercentForBuffering = percent;

            showTip(String.format(context.getString(R.string.tts_toast_format),
                    mPercentForBuffering, mPercentForPlaying));
        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度
            mPercentForPlaying = percent;
            showTip(String.format(context.getString(R.string.tts_toast_format), mPercentForBuffering, mPercentForPlaying));
//            SpannableStringBuilder style=new SpannableStringBuilder(texts);
//            Log.e(TAG,"beginPos = "+beginPos +"  endPos = "+endPos);
//            if(!"henry".equals(voicerCloud)||!"xiaoyan".equals(voicerCloud)||
//                    !"xiaoyu".equals(voicerCloud)||!"catherine".equals(voicerCloud))
//                endPos++;
//            style.setSpan(new BackgroundColorSpan(Color.RED),beginPos,endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error == null) {
                showTip("播放完成");
            } else if (error != null) {
                showTip(error.getPlainDescription(true));
                Log.d("HH",error.toString());
            }
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
            // 若使用本地能力,会话id为null
            // if (SpeechEvent.EVENT_SESSION_ID == eventType) {
            //    String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
            //    Log.d(TAG, "session id =" + sid);
            // }
            // int i = obj.describeContents();
            // Log.d("HH",eventType+"++"+i);
        }
    };


    private void showTip(final String str) {
                mToast.setText(str);
                mToast.show();
    }



    /**
     * 判断
     * @param result
     */
    public void  ff(String result,Context context){
//回答对象,在没有匹配到用户说的话,默认输出语句
        String answer="不好意思,没有听清楚";
//这里的result参数,就是我们通过讯飞听写里最终拿到用户说话的结果
        if(result.contains("你好")){
            answer="你好,我是智能语音助手";
        }else if(result.contains("谁是世界上最帅的人")){
            answer="哈哈,当然是您";
        }else if (result.contains("中午吃什么")) {
            String[] anwserList = new String[]{"火锅", "烧烤", "烤鱼", "麻辣烫"};
            int random = (int) (Math.random() * anwserList.length);
            String anwser = anwserList[random];
        } else if (result.contains("打印机")){
            //doPhotoPrint();
            answer="以为您,打开打印机";
        }else if (result.contains("通讯录")){
            //intentContacts();
        }else if(result.contains("你的名字")||result.contains("你叫什么")) {
            answer="我叫小明,很高兴认识您";
        }else if (result.contains("你有哪些功能")){
            answer="初步完成,功能不完善";
        }else if (result.contains("你能干什么")){
            answer="现在待定,正在开发中";
        }else if (result.contains("做个自我介绍")){
            answer="您好,我是机器人小明,我貌赛潘安,义超关羽,智胜孔明,上知天文,下晓地理,出口成章,提笔成文,懂阴阳,测八卦,知奇门,晓遁甲的,大豪杰,大英雄,大剑客,大宗师,人称山崩地裂水倒流,赶浪无丝鬼见愁,前无古人,后无来者的,天下第一——“帅”呀";
        }else if(result.contains("开相机 ")){
            //摄像投
            //video();
        }else if (result.contains("打电话给张海洋")){
            answer="好的";
        }
        //调用语音助手说话的方法,把回答对象传进去.
        int code = mTts.startSpeaking(answer, mTtsListener);
    }
}
没有更多推荐了,返回首页