zoukankan      html  css  js  c++  java
  • 3D语音天气球(源码分享)——在Unity中使用Android语音服务

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


    开篇废话:


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

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

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

    三:Android语音服务和Unity的消息传递:3D语音天气球(源码分享)——在Unity中使用Android语音服务

    四:Unity3D端和Android端的结合3D语音天气球(源码分享)——完结篇

     

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

     

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

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

        



    语音服务:

    我使用的语音服务是科大讯飞语音,他们的官网是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应用中嵌入Unity3D视图(展示3D模型)



    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球旋转我会在最后一篇文章中介绍。

  • 相关阅读:
    TestNG入门教程-6-enabled和priority属性
    TestNG入门教程-5-timeOut属性
    TestNG入门教程-4-Testng中注释简介
    Unicode、UTF-8 和 ISO8859-1到底有什么区别
    java数目
    sql必知必会-总结篇
    mysql监控、性能调优及三范式理解
    loadrunner常用函数总结
    loadrunner监控度量项及中文解释
    linux下crontab的使用实现
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6168036.html
Copyright © 2011-2022 走看看