轉載請註明本文出自大苞米的博客(http://blog.csdn.net/a396901990),謝謝支持!
php
開篇廢話:html
這個項目準備分四部分介紹:前端
一:建立可旋轉的「3D球」:3D語音天氣球(源碼分享)——建立可旋轉的3D球java
二:經過天氣服務,從網絡獲取時實天氣信息並動態生成「3D球」:3D語音天氣球(源碼分享)——經過天氣服務動態建立3D球android
三:Android語音服務和Unity的消息傳遞:3D語音天氣球(源碼分享)——在Unity中使用Android語音服務git
四:Unity3D端和Android端的結合:3D語音天氣球(源碼分享)——完結篇github
前兩篇文章已經介紹瞭如何建立這個3D球,本篇文章介紹如何在Unity中使用Android的語音服務,最後一篇文章則會介紹如何用聲音控制這個3D球。後端
左邊是Unity作出後在電腦上運行效果圖(本節須要實現的效果)網絡
右邊是Unity結合Android和語音控制以後在手機運行的效果圖(全部都介紹完後的最終效果):app
語音服務:
我使用的語音服務是科大訊飛語音,他們的官網是http://open.voicecloud.cn/index.php/default/speechservice
進入官網下載Android版語音的sdk(須要註冊還有一些爛七八糟的東西,有點小麻煩)
下載后里面有一些開發包和一個使用Demo,這個Demo運行的效果以下:
使用簡介:
我只用到了語音聽寫和語音合成,下面簡單介紹一些這倆個功能的使用。
在使用時須要有一些「初始化」的工做:
AndroidManifest.xml中設置一些權限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
導入開發包:
armeabiso動態庫
mac.jar jar包
代碼中設置權限:
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=540dcea0");
語音聽寫:
就是將說的話轉換成文字。識別率十分準確,基本沒出過錯。
初始化識別對象:
// 初始化識別對象 SpeechRecognizer mVoice = SpeechRecognizer.createRecognizer(this, mInitListener);
設置參數:
// 設置語言 mVoice.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // 設置語言區域 mVoice.setParameter(SpeechConstant.ACCENT, "mandarin"); // 設置語音前端點 mVoice.setParameter(SpeechConstant.VAD_BOS, "4000"); // 設置語音後端點 mVoice.setParameter(SpeechConstant.VAD_EOS, "1000"); // 設置標點符號 mVoice.setParameter(SpeechConstant.ASR_PTT, "0"); // 設置音頻保存路徑 mVoice.setParameter(SpeechConstant.ASR_AUDIO_PATH, "/sdcard/iflytek/wavaudio.pcm");設置聽寫監聽器:
private RecognizerListener recognizerListener=new RecognizerListener(){ @Override public void onBeginOfSpeech() { showTip("開始說話"); } @Override public void onError(SpeechError error) { showTip(error.getPlainDescription(true)); } @Override public void onEndOfSpeech() { showTip("結束說話"); } @Override public void onResult(RecognizerResult results, boolean isLast) { Log.d(TAG, results.getResultString()); String text = JsonParser.parseIatResult(results.getResultString()); mResultText.append(text); mResultText.setSelection(mResultText.length()); if(isLast) { //TODO 最後的結果 } } @Override public void onVolumeChanged(int volume) { showTip("當前正在說話,音量大小:" + volume); } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { } };調用:
mVoice.startListening(voiceListener);
語音合成:
將文字轉換成語音讀出來。
使用方法和上面的語音識別大同小異,你們能夠看代碼,這裏我就不浪費你們時間了。
在設置參數時能夠選擇說話人性別,並且還能夠選擇方言。
我以前用方言合成了點罵人的話聽着特搞siao。。。
PS:我只是很是簡單的介紹一下,若是你們真要使用建議示例代碼配合文檔(下載的壓縮包中能夠找到)好好研究一下。
Unity中使用Android語音服務:
上面簡單介紹瞭如何使用這個語音服務,如今的問題是如何在Unity中調用這個服務。
思路就是將Android項目總體當成一個包/服務/插件,放入Unity的項目中,這樣咱們就能夠在Unity中調用Android的方法。
說到這裏就須要瞭解一下Unity和Android項目結合的知識,相關內容都在我以前寫的一個文章:
Android端代碼:
咱們須要作的就是讓Android的activity都繼承自UnityPlayerActivity。
下面我把Android端的代碼貼出來,結合上面介紹的內容相信你們一看就懂:
public class MainActivity extends UnityPlayerActivity { // 四個按鈕 private Button voiceButton; private Button detailButton; private Button returnButton; private Button quitButton; private Map<String, String> mapAllNameID; boolean isFaild = false; // 語音結果 String voiceResult = null; // 全部的市 private String[] strNamePro; // 全部的城市 private String[][] strNameCity; // 語音聽寫對象 private SpeechRecognizer mVoice; // 語音合成對象 private SpeechSynthesizer mTts; // 默認發音人 private String voicer = "xiaoyan"; // 引擎類型 private String mEngineType = SpeechConstant.TYPE_CLOUD; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test); View playerView = mUnityPlayer.getView(); LinearLayout ll = (LinearLayout) findViewById(R.id.unity_layout); ll.addView(playerView); SpeechUtility.createUtility(this, SpeechConstant.APPID + "=540dcea0"); // 初始化識別對象 mVoice = SpeechRecognizer.createRecognizer(this, mInitListener); // 初始化合成對象 mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener); voiceButton = (Button) findViewById(R.id.voice_btn); voiceButton.setOnClickListener(new voiceListener()); returnButton = (Button) findViewById(R.id.return_btn); returnButton.setOnClickListener(new returnListener()); detailButton = (Button) findViewById(R.id.detail_btn); detailButton.setOnClickListener(new detailListener()); quitButton = (Button) findViewById(R.id.quit_btn); quitButton.setOnClickListener(new quitListener()); initVar(); } public class voiceListener implements OnClickListener { @Override public void onClick(View arg0) { voiceResult = ""; // 設置參數 setParam(); mVoice.startListening(voiceListener); } } public class returnListener implements OnClickListener { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("Main Camera", "back", ""); } } public class detailListener implements OnClickListener { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("Main Camera", "detail", ""); } } public class quitListener implements OnClickListener { @Override public void onClick(View arg0) { System.exit(0); } } public void quitApp(String str) { Toast.makeText(getApplicationContext(), "退出", Toast.LENGTH_SHORT).show(); System.exit(0); } private RecognizerListener voiceListener = new RecognizerListener() { @Override public void onBeginOfSpeech() { Toast.makeText(getApplicationContext(), "開始說話", Toast.LENGTH_SHORT).show(); } @Override public void onError(SpeechError error) { Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show(); } @Override public void onEndOfSpeech() { Toast.makeText(getApplicationContext(), "結束說話", Toast.LENGTH_SHORT).show(); } @Override public void onResult(RecognizerResult results, boolean isLast) { voiceResult = voiceResult + JsonParser.parseIatResult(results.getResultString()); if (isLast) { setSpeakParam(); mTts.startSpeaking(checkResult(voiceResult), mTtsListener); // UnityPlayer.UnitySendMessage("Main Camera","voice",getResults(voiceResult)); } } @Override public void onVolumeChanged(int volume) { // Toast.makeText(getApplicationContext(), "當前正在說話,音量大小:" + volume, Toast.LENGTH_SHORT).show(); } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { } }; /** * 合成回調監聽。 */ private SynthesizerListener mTtsListener = new SynthesizerListener() { @Override public void onSpeakBegin() { } @Override public void onSpeakPaused() { } @Override public void onSpeakResumed() { } @Override public void onBufferProgress(int percent, int beginPos, int endPos, String info) { } @Override public void onSpeakProgress(int percent, int beginPos, int endPos) { } @Override public void onCompleted(SpeechError error) { if (error == null) { if (!isFaild) { // 向Unity發送語音獲得結果 UnityPlayer.UnitySendMessage("Main Camera", "voice", voiceResult); } } else if (error != null) { Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show(); } } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { } }; // 設置語音識別的參數 public void setParam() { // 設置語言 mVoice.setParameter(SpeechConstant.LANGUAGE, "zh_cn"); // 設置語言區域 mVoice.setParameter(SpeechConstant.ACCENT, "mandarin"); // 設置語音前端點 mVoice.setParameter(SpeechConstant.VAD_BOS, "4000"); // 設置語音後端點 mVoice.setParameter(SpeechConstant.VAD_EOS, "1000"); // 設置標點符號 mVoice.setParameter(SpeechConstant.ASR_PTT, "0"); // 設置音頻保存路徑 mVoice.setParameter(SpeechConstant.ASR_AUDIO_PATH, "/sdcard/iflytek/wavaudio.pcm"); } // 設置語音合成參數 private void setSpeakParam() { // 設置合成 if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) { mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 設置發音人 mTts.setParameter(SpeechConstant.VOICE_NAME, voicer); } else { mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL); // 設置發音人 voicer爲空默認經過語音+界面指定發音人。 mTts.setParameter(SpeechConstant.VOICE_NAME, ""); } // 設置語速 mTts.setParameter(SpeechConstant.SPEED, "50"); // 設置音調 mTts.setParameter(SpeechConstant.PITCH, "50"); // 設置音量 mTts.setParameter(SpeechConstant.VOLUME, "50"); // 設置播放器音頻流類型 mTts.setParameter(SpeechConstant.STREAM_TYPE, "3"); } /** * 初始化監聽器。 */ private InitListener mInitListener = new InitListener() { @Override public void onInit(int code) { if (code != ErrorCode.SUCCESS) { Toast.makeText(getApplicationContext(), "初始化失敗,錯誤碼:" + code, Toast.LENGTH_SHORT).show(); } } }; /** * 初期化監聽。 */ private InitListener mTtsInitListener = new InitListener() { @Override public void onInit(int code) { if (code != ErrorCode.SUCCESS) { Toast.makeText(getApplicationContext(), "初始化失敗,錯誤碼:" + code, Toast.LENGTH_SHORT).show(); } } }; }
上面並非所有的代碼,Android端的所有代碼我已經上傳到GitHub:
https://github.com/a396901990/3D_Sphere/tree/feature/Voice_Weather_3D_Sphere
項目中3DVoiceWeather文件就是Android項目,你們能夠導入到Eclipse中查看。
上面代碼已是完整代碼了,按照網上教程中的方法,將Android項目以插件的形式放入Unity中,最後在Unity中build成apk就能夠在手機中使用了。
如何使用語音控制3D球旋轉我會在最後一篇文章中介紹。