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

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

开篇废话:

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

一:创建可旋转的“3D球”:3D语音天气球(源码分享)——创建可旋转的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中设置一些权限:

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

时间: 2024-10-05 10:25:39

3D语音天气球——在Unity中使用Android语音服务的相关文章

Unity中加入Android项目的Build步骤

简介: 有的项目需要在Android中加入Unity功能,例如ANDROID应用中嵌入Unity3D视图(展示3D模型) 有的项目需要在Unity中加入Android功能,例如3D语音天气球(源码分享)——创建可旋转的3D球 由于Android中的功能和代码只能当作一个Unity插件,需要在Unity进行最终的Build后生成apk文件运行. 所以无论上面两种情况都涉及了在Unity中加入Android项目的Build步骤: 步骤: 1.确保Android工程代码正确,然后在Eclipse中bu

针对Android平台我们需要学习如何在Unity中调用Android的JAVA代码。

Unity for Android 比较特殊,Unity for IOS 打包是将XCODE工程直接交给开发者,开发者可以在工程的基础上继续添加新的视图,最后由开发者自行打包生成IPA包,发布程序.而Unity for Android打包直接生成APK包,等于说源代码开发者是看不到的,但是Unity的自身确实有些局限,针对Android平台我们需要学习如何在Unity中调用Android的JAVA代码.本章我们的目标是使用Unity的脚本打开Activity.首先我们创建一个普通的Android

在 Unity 中使用 Android SDK

如果你想知道什么是爱.我们从哪里来.生命的意义.宇宙的起源,那么请不要看这篇文章. 这只是一篇无聊的文章,除非你是一只正在被折磨的猿猴,否则请跳过. 将 Java 代码做成 Unity 插件 下载 Android sdk.在 Unity 中配置好路径,保证 Unity 可以正常导出 apk:下载 JDK .配置好环境变量,保证 Eclipse 可以正常打开.另外你需要知道使用Eclipse的logcat查看调试log. 1.打开 Eclipse,建立一个 Android 空项目,注意 packa

3D语音天气球(源码分享)——完结篇

开篇废话: 由于这篇文章是本系列最后一篇,有必要进行简单的回顾和思路整理. 这个程序是由两部分组成,Android端和Unity端: 1.Unity端负责3D球的创建,显示和旋转:3D语音天气球(源码分享)--创建可旋转的3D球 2.通过天气服务动态创建3D球:3D语音天气球(源码分享)--通过天气服务动态创建3D球 3.Android端使用第三方的语音服务来进行语音识别:3D语音天气球(源码分享)--在Unity中使用Android语音服务 4.Unity中加入Android项目:Unity中

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

开篇废话: 在9月份时参加了一个网站的比赛,比赛的题目是需要使用第三方平台提供的服务做出创意的作品. 于是我选择使用语音服务,天气服务,Unity3D,Android来制作一个3D语音天气预报,我给它起名叫做3D语音天气球(好土...) 虽然没获奖但我觉得这个项目中还是有些东西比较有创意的,所以打算分享出来,或许有人会用到. 下面简单看下效果图: 左边是Unity做出后在电脑上运行效果图 右边是Unity结合Android和语音控制之后在手机运行的效果图(手机不会做GIF):      瞅着还不

3D语音天气球(源码分享)——通过天气服务动态创建3D球

转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3D语音天气球(源码分享)--创建可旋转的3D球 二:通过天气服务,从网络获取时实天气信息并动态生成"3D球" 三:Android语音服务和Unity的消息传递 四:Unity3D端和Android端的结合 关于项目的详细介绍和3D球的创建请看上面第一篇文章(重要) 今天主要讲解如何通过获取

Android源码:3D语音天气球

3D语音天气球                                                                                                 支持平台:Android    运行环境:Android    开发语言:Java                                                                                                        

3D语音天气球_Android源码

3D语音天气球 通过Android和Unity的结合,以3D滚动球的形式展示全国所有省市天气情况,支持手势和语音两种操作模式. 下载地址:http://www.devstore.cn/code/info/204.html 运行截图:     版权声明:本文为博主原创文章,未经博主允许不得转载.

关于Unity中的3D拾取

3D拾取 3D游戏实际上看到的是2D画面,我们在屏幕上点击,想要找到哪个3D物体,我们实际上是在一个2维平面内做3D拾取. 3D拾取实际上是,当玩家点击屏幕的时候,会从显示屏幕的摄像头发射一条射线,射到它所照射的平面上,射线第一次碰撞到的物体就是玩家所选的物体. 1: 游戏中需要用户触摸/点击 操作3D世界里面的3D物体,那么需要判断用户点击的是3D中的哪个物体;2: 3D拾取的原理: 从摄像机到屏幕空间的触摸点发出一条射线,这条射线第一个撞到哪个3D物体就会认为哪个3D物体被用户选择;3: 代