3D语音天气球——在Unity中使用Android语音服务

来源:互联网 发布:淘宝备份模板找不到了 编辑:程序博客网 时间:2024/05/17 08:12

转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持!


开篇废话:


这个项目准备分四部分介绍:

一:创建可旋转的“3D3D语音天气球(源码分享)——创建可旋转的3D

二:通过天气服务,从网络获取时实天气信息并动态生成“3D”:3D语音天气球(源码分享)——通过天气服务动态创建3D球

三:Android语音服务和Unity的消息传递

四:Unity3D端和Android端的结合

 

前两篇文章已经介绍了如何创建这个3D球,本篇文章介绍如何在Unity中使用Android的语音服务,最后一篇文章则会介绍如何用声音控制这个3D球。

 

左边是Unity做出后在电脑上运行效果图(本节需要实现的效果)

右边是Unity结合Android和语音控制之后在手机运行的效果图(所有都介绍完后的最终效果):

    



语音服务:

我使用的语音服务是科大讯飞语音,他们的官网是http://open.voicecloud.cn/index.php/default/speechservice

进入官网下载Android版语音的sdk(需要注册还有一些烂七八糟的东西,有点小麻烦)

下载后里面有一些开发包和一个使用Demo,这个Demo运行的效果如下:



使用简介:

我只用到了语音听写语音合成,下面简单介绍一些这俩个功能的使用。


在使用时需要有一些“初始化”的工作:

AndroidManifest.xml中设置一些权限:

[html] view plaincopyprint?
  1. <uses-permission android:name="android.permission.RECORD_AUDIO" />  
  2. <uses-permission android:name="android.permission.INTERNET" />  
  3. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  4. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
  5. <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />  
  6. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  7. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
  8. <uses-permission android:name="android.permission.READ_CONTACTS" />  
  9. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  

导入开发包:

armeabiso动态库

mac.jar jar包


代码中设置权限:

[java] view plaincopyprint?
  1. SpeechUtility.createUtility(this, SpeechConstant.APPID + "=540dcea0");  

语音听写:

就是将说的话转换成文字。识别率十分准确,基本没出过错。

初始化识别对象:

[java] view plaincopyprint?
  1. // 初始化识别对象  
  2. SpeechRecognizer mVoice = SpeechRecognizer.createRecognizer(this, mInitListener);  

设置参数:

[java] view plaincopyprint?
  1. // 设置语言  
  2. mVoice.setParameter(SpeechConstant.LANGUAGE, "zh_cn");  
  3. // 设置语言区域  
  4. mVoice.setParameter(SpeechConstant.ACCENT, "mandarin");  
  5.   
  6. // 设置语音前端点  
  7. mVoice.setParameter(SpeechConstant.VAD_BOS, "4000");  
  8. // 设置语音后端点  
  9. mVoice.setParameter(SpeechConstant.VAD_EOS, "1000");  
  10. // 设置标点符号  
  11. mVoice.setParameter(SpeechConstant.ASR_PTT, "0");  
  12. // 设置音频保存路径  
  13. mVoice.setParameter(SpeechConstant.ASR_AUDIO_PATH, "/sdcard/iflytek/wavaudio.pcm");  
设置听写监听器:
[java] view plaincopyprint?
  1. private RecognizerListener recognizerListener=new RecognizerListener(){  
  2.     @Override  
  3.     public void onBeginOfSpeech() {   
  4.         showTip("开始说话");  
  5.     }  
  6.   
  7.     @Override  
  8.     public void onError(SpeechError error) {  
  9.         showTip(error.getPlainDescription(true));  
  10.     }  
  11.   
  12.     @Override  
  13.     public void onEndOfSpeech() {  
  14.         showTip("结束说话");  
  15.     }  
  16.   
  17.     @Override  
  18.     public void onResult(RecognizerResult results, boolean isLast) {          
  19.         Log.d(TAG, results.getResultString());  
  20.         String text = JsonParser.parseIatResult(results.getResultString());  
  21.         mResultText.append(text);  
  22.         mResultText.setSelection(mResultText.length());  
  23.         if(isLast) {  
  24.             //TODO 最后的结果  
  25.         }  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onVolumeChanged(int volume) {  
  30.         showTip("当前正在说话,音量大小:" + volume);  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {  
  35.     }  
  36. };  
调用:
[java] view plaincopyprint?
  1. mVoice.startListening(voiceListener);  


语音合成:

将文字转换成语音读出来。

使用方法和上面的语音识别大同小异,大家可以看代码,这里我就不浪费大家时间了。

在设置参数时可以选择说话人性别,而且还可以选择方言。

我之前用方言合成了点骂人的话听着特搞siao。。。

PS:我只是非常简单的介绍一下,如果大家真要使用建议示例代码配合文档(下载的压缩包中可以找到)好好研究一下。



Unity中使用Android语音服务:

上面简单介绍了如何使用这个语音服务,现在的问题是如何在Unity中调用这个服务。

思路就是将Android项目整体当成一个包/服务/插件,放入Unity的项目中,这样我们就可以在Unity中调用Android的方法。

说到这里就需要了解一下Unity和Android项目结合的知识,相关内容都在我之前写的一个文章:

ANDROID应用中嵌入Unity3D视图(展示3D模型)



Android端代码:

我们需要做的就是让Android的activity都继承自UnityPlayerActivity。

下面我把Android端的代码贴出来,结合上面介绍的内容相信大家一看就懂:

[java] view plaincopyprint?
  1. public class MainActivity extends UnityPlayerActivity {  
  2.     // 四个按钮  
  3.     private Button voiceButton;  
  4.     private Button detailButton;  
  5.     private Button returnButton;  
  6.     private Button quitButton;  
  7.       
  8.     private Map<String, String> mapAllNameID;  
  9.     boolean isFaild = false;  
  10.       
  11.     // 语音结果  
  12.     String voiceResult = null;  
  13.     // 所有的市  
  14.     private String[] strNamePro;  
  15.     // 所有的城市  
  16.     private String[][] strNameCity;  
  17.     // 语音听写对象  
  18.     private SpeechRecognizer mVoice;  
  19.     // 语音合成对象  
  20.     private SpeechSynthesizer mTts;  
  21.     // 默认发音人  
  22.     private String voicer = "xiaoyan";  
  23.     // 引擎类型  
  24.     private String mEngineType = SpeechConstant.TYPE_CLOUD;  
  25.   
  26.     @Override  
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.test);  
  30.   
  31.         View playerView = mUnityPlayer.getView();  
  32.         LinearLayout ll = (LinearLayout) findViewById(R.id.unity_layout);  
  33.         ll.addView(playerView);  
  34.   
  35.         SpeechUtility.createUtility(this, SpeechConstant.APPID + "=540dcea0");  
  36.         // 初始化识别对象  
  37.         mVoice = SpeechRecognizer.createRecognizer(this, mInitListener);  
  38.         // 初始化合成对象  
  39.         mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);  
  40.   
  41.         voiceButton = (Button) findViewById(R.id.voice_btn);  
  42.         voiceButton.setOnClickListener(new voiceListener());  
  43.   
  44.         returnButton = (Button) findViewById(R.id.return_btn);  
  45.         returnButton.setOnClickListener(new returnListener());  
  46.   
  47.         detailButton = (Button) findViewById(R.id.detail_btn);  
  48.         detailButton.setOnClickListener(new detailListener());  
  49.   
  50.         quitButton = (Button) findViewById(R.id.quit_btn);  
  51.         quitButton.setOnClickListener(new quitListener());  
  52.         initVar();  
  53.     }  
  54.   
  55.     public class voiceListener implements OnClickListener {  
  56.         @Override  
  57.         public void onClick(View arg0) {  
  58.             voiceResult = "";  
  59.             // 设置参数  
  60.             setParam();  
  61.             mVoice.startListening(voiceListener);  
  62.         }  
  63.     }  
  64.   
  65.     public class returnListener implements OnClickListener {  
  66.         @Override  
  67.         public void onClick(View arg0) {  
  68.             UnityPlayer.UnitySendMessage("Main Camera""back""");  
  69.         }  
  70.     }  
  71.   
  72.     public class detailListener implements OnClickListener {  
  73.         @Override  
  74.         public void onClick(View arg0) {  
  75.             UnityPlayer.UnitySendMessage("Main Camera""detail""");  
  76.         }  
  77.     }  
  78.   
  79.     public class quitListener implements OnClickListener {  
  80.         @Override  
  81.         public void onClick(View arg0) {  
  82.             System.exit(0);  
  83.         }  
  84.     }  
  85.   
  86.     public void quitApp(String str) {  
  87.         Toast.makeText(getApplicationContext(), "退出", Toast.LENGTH_SHORT).show();  
  88.         System.exit(0);  
  89.     }  
  90.   
  91.     private RecognizerListener voiceListener = new RecognizerListener() {  
  92.         @Override  
  93.         public void onBeginOfSpeech() {  
  94.             Toast.makeText(getApplicationContext(), "开始说话", Toast.LENGTH_SHORT).show();  
  95.         }  
  96.   
  97.         @Override  
  98.         public void onError(SpeechError error) {  
  99.             Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();  
  100.         }  
  101.   
  102.         @Override  
  103.         public void onEndOfSpeech() {  
  104.             Toast.makeText(getApplicationContext(), "结束说话", Toast.LENGTH_SHORT).show();  
  105.         }  
  106.   
  107.         @Override  
  108.         public void onResult(RecognizerResult results, boolean isLast) {  
  109.             voiceResult = voiceResult + JsonParser.parseIatResult(results.getResultString());  
  110.             if (isLast) {  
  111.                 setSpeakParam();  
  112.                 mTts.startSpeaking(checkResult(voiceResult), mTtsListener);  
  113.                 // UnityPlayer.UnitySendMessage("Main Camera","voice",getResults(voiceResult));  
  114.             }  
  115.         }  
  116.   
  117.         @Override  
  118.         public void onVolumeChanged(int volume) {  
  119.             // Toast.makeText(getApplicationContext(), "当前正在说话,音量大小:" + volume, Toast.LENGTH_SHORT).show();  
  120.         }  
  121.   
  122.         @Override  
  123.         public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {  
  124.         }  
  125.     };  
  126.   
  127.     /** 
  128.      * 合成回调监听。 
  129.      */  
  130.     private SynthesizerListener mTtsListener = new SynthesizerListener() {  
  131.         @Override  
  132.         public void onSpeakBegin() {  
  133.   
  134.         }  
  135.   
  136.         @Override  
  137.         public void onSpeakPaused() {  
  138.   
  139.         }  
  140.   
  141.         @Override  
  142.         public void onSpeakResumed() {  
  143.   
  144.         }  
  145.   
  146.         @Override  
  147.         public void onBufferProgress(int percent, int beginPos, int endPos, String info) {  
  148.         }  
  149.   
  150.         @Override  
  151.         public void onSpeakProgress(int percent, int beginPos, int endPos) {  
  152.   
  153.         }  
  154.   
  155.         @Override  
  156.         public void onCompleted(SpeechError error) {  
  157.             if (error == null) {  
  158.                 if (!isFaild) {  
  159.                     // 向Unity发送语音得到结果  
  160.                     UnityPlayer.UnitySendMessage("Main Camera""voice", voiceResult);  
  161.                 }  
  162.             } else if (error != null) {  
  163.                 Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();  
  164.             }  
  165.         }  
  166.   
  167.         @Override  
  168.         public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {  
  169.   
  170.         }  
  171.     };  
  172.   
  173.     // 设置语音识别的参数  
  174.     public void setParam() {  
  175.         // 设置语言  
  176.         mVoice.setParameter(SpeechConstant.LANGUAGE, "zh_cn");  
  177.         // 设置语言区域  
  178.         mVoice.setParameter(SpeechConstant.ACCENT, "mandarin");  
  179.         // 设置语音前端点  
  180.         mVoice.setParameter(SpeechConstant.VAD_BOS, "4000");  
  181.         // 设置语音后端点  
  182.         mVoice.setParameter(SpeechConstant.VAD_EOS, "1000");  
  183.         // 设置标点符号  
  184.         mVoice.setParameter(SpeechConstant.ASR_PTT, "0");  
  185.         // 设置音频保存路径  
  186.         mVoice.setParameter(SpeechConstant.ASR_AUDIO_PATH, "/sdcard/iflytek/wavaudio.pcm");  
  187.     }  
  188.       
  189.     // 设置语音合成参数  
  190.     private void setSpeakParam() {  
  191.         // 设置合成  
  192.         if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) {  
  193.             mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);  
  194.             // 设置发音人  
  195.             mTts.setParameter(SpeechConstant.VOICE_NAME, voicer);  
  196.         } else {  
  197.             mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);  
  198.             // 设置发音人 voicer为空默认通过语音+界面指定发音人。  
  199.             mTts.setParameter(SpeechConstant.VOICE_NAME, "");  
  200.         }  
  201.         // 设置语速  
  202.         mTts.setParameter(SpeechConstant.SPEED, "50");  
  203.         // 设置音调  
  204.         mTts.setParameter(SpeechConstant.PITCH, "50");  
  205.         // 设置音量  
  206.         mTts.setParameter(SpeechConstant.VOLUME, "50");  
  207.         // 设置播放器音频流类型  
  208.         mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");  
  209.     }  
  210.       
  211.     /** 
  212.      * 初始化监听器。 
  213.      */  
  214.     private InitListener mInitListener = new InitListener() {  
  215.   
  216.         @Override  
  217.         public void onInit(int code) {  
  218.             if (code != ErrorCode.SUCCESS) {  
  219.                 Toast.makeText(getApplicationContext(), "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();  
  220.             }  
  221.         }  
  222.     };  
  223.   
  224.     /** 
  225.      * 初期化监听。 
  226.      */  
  227.     private InitListener mTtsInitListener = new InitListener() {  
  228.         @Override  
  229.         public void onInit(int code) {  
  230.   
  231.             if (code != ErrorCode.SUCCESS) {  
  232.                 Toast.makeText(getApplicationContext(), "初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();  
  233.             }  
  234.         }  
  235.     };  
  236. }  


上面并不是全部的代码,Android端的全部代码我已经上传到GitHub:

https://github.com/a396901990/3D_Sphere/tree/feature/Voice_Weather_3D_Sphere

项目中3DVoiceWeather文件就是Android项目,大家可以导入到Eclipse中查看。


上面代码已经是完整代码了,按照网上教程中的方法,将Android项目以插件的形式放入Unity中,最后在Unity中build成apk就可以在手机中使用了。

如何使用语音控制3D球旋转我会在最后一篇文章中介绍。
0 0
原创粉丝点击