Sotaのしゃべりを調整するアプリを作る

こんにちは、竹石です。

Sotaは日本語は結構上手だと個人的に思っていますが、

変になってしまうこともあるので、喋りを調整するアプリを作りたいと思います。

Sotaの喋りは用意した音声ファイルの再生と、

テキストからVStoneのAPIで音声ファイルをDLして再生するものがありますが、

変数や乱数で喋る内容を変えたい場合が多いので、基本的に後者を使います。

GlobalVariable.sotawish.Say("こんにちは", MotionAsSotaWish.MOTION_TYPE_HELLO, speechRate, pitch, intonation);

やることは↑のパラメータをブラウザのgetで受け取って、Sotaが喋ると言うだけです。

クラスは2つです。

Main.java

package jp.co.headwaters.sota.main;

import jp.co.headwaters.sota.main.receiver.Connect;
import jp.vstone.RobotLib.CRobotMem;
import jp.vstone.RobotLib.CRobotPose;
import jp.vstone.RobotLib.CRobotUtil;
import jp.vstone.RobotLib.CSotaMotion;
import jp.vstone.network.TCPIPServer;
import jp.vstone.sotatalk.MotionAsSotaWish;
import jp.vstone.sotatalk.SpeechRecog;

public class Main {

	public static void main(String[] args) {
		if (GlobalVariable.mem.Connect()) {
			GlobalVariable.motion.InitRobot_Sota();
			if (GlobalVariable.InitServoOn) {
				GlobalVariable.motion.ServoOn();
				CRobotPose pose = new CRobotPose();
				pose.SetPose(new Byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }, new Short[] { 0, -900, 0, 900, 0, 0, 0, 0 });
				pose.SetLed(new Byte[] { 0, 1, 2, 8, 9, 10, 11, 12, 13 },
						new Short[] { 0, -255, 0, 180, 80, 0, 180, 80, 0 });
				GlobalVariable.motion.play(pose, 1500);
				CRobotUtil.wait(1500);
			}

			try {
				Connect con = new Connect();
				con.receive();
			} catch (Exception e) {
				System.out.println("例外が発生しました:");
				e.printStackTrace();
			}
			System.exit(0);
		}
	}

	public static class GlobalVariable {
		public static CRobotMem mem = new CRobotMem();
		public static CSotaMotion motion = new CSotaMotion(mem);
		public static boolean InitServoOn = true;
		public static boolean TRUE = true;
		public static Object recvReturnValue;
		public static SpeechRecog recog = new SpeechRecog(motion);
		public static MotionAsSotaWish sotawish = new MotionAsSotaWish(motion);
		public static TCPIPServer tcpipServer = new TCPIPServer((short) 5001, (int) 5000);
	}
}

Connect.java

package jp.co.headwaters.sota.main.receiver;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

import jp.co.headwaters.sota.main.Main.GlobalVariable;
import jp.vstone.sotatalk.MotionAsSotaWish;
import jp.vstone.sotatalk.SpeechRecog.SpeechRecogAbortException;

public class Connect {

	public String receive() throws SpeechRecogAbortException {
		if (!GlobalVariable.TRUE) throw new SpeechRecogAbortException("default");
		{
			while (true) {
				try {
					String req = GlobalVariable.tcpipServer.waitRequest();
					if (req == null)
						req = "";
					else {
						int speechRate = 11;
						int pitch = 13;
						int intonation = 11;
						if (isIncludeWord(req, "rate"))
							speechRate = Integer.valueOf(getParam(req, "rate"));
						if (isIncludeWord(req, "pitch"))
							pitch = Integer.valueOf(getParam(req, "pitch"));
						if (isIncludeWord(req, "intonation"))
							intonation = Integer.valueOf(getParam(req, "intonation"));
						if (isIncludeWord(req, "say")) {
							GlobalVariable.sotawish.Say(getSay(req), MotionAsSotaWish.MOTION_TYPE_HELLO, speechRate,
									pitch, intonation);
						}
					}
				} catch (Exception e) {
				}
			}
		}
	}

	private static boolean isIncludeWord(String target, String keyword) {
		if (target == null || target == "") return false;
		return target.contains(keyword);
	}

	private static String getParam(String target, String key) throws UnsupportedEncodingException {
		target = URLDecoder.decode(target, StandardCharsets.UTF_8.toString());
		int index = target.indexOf(key + "=");
		int lastIndex = target.lastIndexOf("&");
		if (lastIndex < index) {
			return target.substring(index + key.length() + 1, target.indexOf(" HTTP"));
		} else {
			String l_params = target.substring(index + key.length() + 1, target.indexOf(" HTTP"));
			int l_index = l_params.indexOf("&");
			return l_params.substring(0, l_index);
		}
	}

	private static String getSay(String target) throws UnsupportedEncodingException {
		target = URLDecoder.decode(target, StandardCharsets.UTF_8.toString());
		String key = "say";
		int index = target.indexOf(key + "=");
		int end = target.indexOf("&");
		if (end != -1) {
			return target.substring(index + key.length() + 1, end);
		} else {
			return target.substring(index + key.length() + 1, target.indexOf(" HTTP"));
		}
	}
}

あとは、jarにして、実行すれば、同じWifiに接続したPCからのgetでSotaが喋ります。

http://SotaのIP:5001/?say=おっす、ソータだよ!&rate=11&pitch=13&intonation=11

これで、Sotaのしゃべりを簡単に調整できますね。

まとめ

アニメーションの調整は流石にVstoneMagicでやったほうが楽ですが、

その他の処理は実装した方が簡単だと思います。

あと、2017/1/11のアップデートで喋る処理が早くなった気がします!

Sotaのニュース

ABOUTこの記事をかいた人

アバター

WEBアプリ開発をメイン業務としている。後輩エンジニアの育成リーダーとしても活躍中。社内勉強会の立ち上げなど、会社の前線でその能力を発揮している。2009年、株式会社ヘッドウォータース新卒入社。