Up:[[Tutorial]] Previous:[[エージェント間のメッセージのやりとり]] Next:[[視覚に関する操作]] #contents *音声認識 [#t40318dd] ここではSIGVerseで音声認識を行う方法を説明します。 ※NIIサーバではSIGVerseのバージョン101104以降で正常に動作します。また、音声認識を行うためには、SIGVerseのインストール時にJulius(音声認識を行うソフト)やdictation-kitの場所を指定する必要があります。指定方法は[[こちら>SIGVerseのインストール(NIIサーバ)]] **音声データ(waveファイル)の音声認識 [#pc99087f] ここではあらかじめ用意されているサンプルの音声データ(waveファイル)を音声認識してみたいと思います。 ***コントローラ作成 [#m6feace7] 音声データを受け取り、音声認識を行うエージェントのコントローラを作成します。 $ cd ~/sigverse-<version>/bin/NewWorld $ emacs soundRecog.cpp soundRecog.cpp #highlight(cpp){{ #include <Controller.h> #include <ControllerEvent.h> #include <RawSound.h> #include <Logger.h> #include <Text.h> class AgentController : public Controller { public: //音声データを受け取った時に呼出される関数onRecvSoundの利用を宣言します。 void onRecvSound(RecvSoundEvent &evt); }; void AgentController::onRecvSound(RecvSoundEvent &evt) { //音声データを取得します。 RawSound * sound = evt.getRawSound(); //音声ヘッダを取得します。 RawSoundHeader &h = sound->getHeader(); LOG_MSG(("channel = %d", h.getChannelNum())); LOG_MSG(("sampling rate = %u", h.getSamplingRate())); //エンディアンを得ます。 RawSoundEndian endian = h.getEndian(); LOG_MSG(("endian : %s", endian == RAW_SOUND_LITTLE_ENDIAN? "little": "big")); // 生の WAVデータを取得します。 int datalen = sound->getDataLen(); char * data = sound->getData(); // 音声認識結果をテキストで取得します。 Text * text = getText(*sound); if (text) { // 音声認識結果を表示します。 const char * str = text->getString(); LOG_MSG(("text : %s", str)); // 必要なくなったらテキストデータをdeleteします。 delete text; } } extern "C" Controller * createController () { return new AgentController; } }} 音声認識した結果を表示するサンプルです。 ***コンパイル [#gdda3ca6] Makefileを修正します。 $ emacs Makefile オブジェクトファイルの指定のところをsoundRecog.soを指定します。 #オブジェクトファイルの指定 OBJS = soundRecog.so #ref(makefile_sound) コンパイルします。 $ make ***世界ファイル作成 [#l5f5ce8b] $ cd .. $ emacs xml/soundRecog.xml soundRecog.xml #highlight(xml){{ <?xml version="1.0" encoding="utf8"?> <world name="myworld4"> <gravity x="0.0" y="-9.8" z="0.0"/> <!--音声データ受信エージェントRobot-niiの設定--> <instanciate class="Robot-nii.xml"> <set-attr-value name="name" value="robot_000"/> <set-attr-value name="language" value="c++"/> <!--音声データ受信者のコントローラ指定--> <set-attr-value name="implementation" value="./NewWorld/soundRecog.so"/> <!--動力学演算をfalseに設定--> <set-attr-value name="dynamics" value="false"/> <!--エージェントの位置(x,y,z)--> <set-attr-value name="x" value="0.0"/> <set-attr-value name="y" value="60.0"/> <set-attr-value name="z" value="-60.0"/> </instanciate> }} これで準備完了です。 ***SIGVerse,Juliusの起動 [#q211f39e] まずSIGVerseを起動します。 $ ./sigserver.sh -p 9001 -w soundRecog.xml & 次にJuliusを起動します。エンターキーを押してコマンドを続行します。 $ ./sigjsp.sh -p 9001 sigjsp.shというシェルスクリプトでJuliusを起動します。このときシミュレーションサーバが起動しているポート番号を-pオプションで指定してJuliusが起動したことをシミュレーションサーバに知らせます。 以下のようなメッセージが表示されればJuliusは正常に起動しています。正常に起動しない場合は[[Juliusの設定>#w9e5b872]]を参照ください。 Stat: adin_tcpip: waiting connection... =================================== julius adinnet port connect ok! Stat: server-client: connect from 127.0.0.1 Stat: adin_tcpip: connected =================================== *************************************** *** julius successfully started *** *************************************** ******************************************************* connect to SimServer (localhost:9111) ok ******************************************************* clerkName (socio.iir.nii.ac.jp) send COMM_REQUEST_PROVIDE_SERVICE ok waiting for connection ... (accept sock: 7) [SYS] socio.iir.nii.ac.jp:7500 : service provider [SYS] 127.0.0.1 connected ***SIGViewerから音声データの送信 [#jac958b8] SIGVerse,Juliusが起動している状態で、クライアント側でSIGViewerを起動し、サーバに接続します。接続が完了するとロボット型エージェントが立っているのが見えると思います。 次にSIM_STRL_CMDがSTARTとなっている状態で、"send"ボタンを押してシミュレーションを開始し、右上にあるCommandタブをクリックします。一番上の入力欄はgeneralとvoiceを選択できるようになっています。ここではvoiceを選択します。次に"送信対象選択"ボタンをクリックしてロボット型エージェントをクリックします。次に"Send Voice"ボタンをクリックします。 #ref(sound_1.jpg) 送信する音声データを選択するダイアログが表示されるので、SIGViewerをインストールしている場所、デフォルトでは C:\Program Files\SIGViewer_<version>\SIGViewer\release にあるsample.wavを選択して、音声データを送信します。 すると以下のようなメッセージが表示され、 「貧乏参考ください」という音声認識結果が表示されると思います。 connection accepted. (sock=8) waiting for connection ... (accept sock: 7) connection accepted. (sock=8) waiting for connection ... (accept sock: 7) [MSG] robot_000(127.0.0.1) channel = 0 [MSG] robot_000(127.0.0.1) sampling rate = 0 [MSG] robot_000(127.0.0.1) endian : little [MSG] robot_000(127.0.0.1) text : 貧乏参考ください。 音声データ(sample.wav)を聞いていみると「リンゴを三個ください」と言っているので、少し間違って認識されているのがわかります。 ※SIGVerseを終了してもJuliusだけが起動しつづていることがありますので注意してください。以下のコマンドで起動中のプロセスを確認できます。 $ ps aux | grep <username> **Juliusの設定 [#w9e5b872] SIGVerseはjuliusのモジュールモードを使って通信を行います.また、音声データはadinnetというjuliusの提供するネットワーク経由での音声入力ポートを使用します. juliusとシミュレーションサーバの通信を行うためのポート番号が他のユーザーと重複している場合Juliusは正常に起動しません。ここではこれらのポート番号の設定方法を説明します。 ***Juliusサーバの設定 [#ee41288b] まずディクテーションキットを自分のホームディレクトリにコピーします。(またはサイトからダウンロードしてきます。) $ cp -r /usr/local/share/dictation-kit-v4.0 ~/ 次にコピーしたディレクトリの中にSIGVerse用に設定されたJulius設定ファイルがすでに用意されています。この設定ファイルを修正します。 ダウンロードした場合は設定ファイルをこちらに置き換えてください。 #ref(fast.jconf) $ emacs ~/dictation-kit-v4.0/fast.jconf ここでサーバモジュールモード、adinnetのポート番号を設定します。以下の2点を修正します。 -サーバモジュールモードのポート番号 ###################################################################### #### サーバーモジュールモード ###################################################################### -module # サーバーモジュールモードで起動 ↓ ###################################################################### #### サーバーモジュールモード ###################################################################### -module 10511 # サーバーモジュールモードで起動 -adinnetポート番号 ###################################################################### #### 音声入力ソース ###################################################################### ## どれかを選んでください(デフォルト:mfcfile) (省略) -input adinnet ↓ ###################################################################### #### 音声入力ソース ###################################################################### ## どれかを選んでください(デフォルト:mfcfile) (省略) -input adinnet -adport 10522 ここではadinnetポート番号を10511, モジュールポート番号を10522としました。他のユーザーと重複しにくい番号に変更することをお勧めします。 ***シミュレーションサーバの設定 [#t8869d80] 次にシミュレーションサーバの設定を行います。 Julius起動時にシミュレーションサーバは以下の設定ファイルを読み込みます。見てみましょう。 $ emacs /home/<usrname>/sigverse-<version>/share/sigverse/etc/sigjsp.conf デフォルトでは以下のようになっています。 # ************************************************************ # sigjsp configuration file # ************************************************************ # ====================================================== # SimServer hostname and port number # ====================================================== SERVER=localhost PORT=7000 # ====================================================== # Port number that sigjsp waiting for connection # ====================================================== SERVICE_PORT=7500 # ====================================================== # julius port number # ====================================================== JULIUS_MODULE_PORT=10500 JULIUS_ADINNET_PORT=5530 # ====================================================== # julius path (not directory, path to executable) # ====================================================== JULIUS_PATH=/usr/local/bin/julius # ====================================================== # julius config file # # [remark] # when relative path is specified, actual path is # calculated from current directory. # (ex) # JULIUS_CONFIG_FILE=fast.jconf # $ pwd # /home/somebody # $ sigjsp # ---> sigjsp searches for /home/somebody/fast.jconf # ====================================================== JULIUS_CONFIG_FILE=/usr/local/share/dictation-kit-v4.0/fast.jconf # ====================================================== # some wait time to finish starting julius (in msec) # ====================================================== # DELAY_TIME_FOR_START_JULIUS=3000 ここでは以下の設定が行えます。 -シミュレーションサーバのポート番号(デフォルト7000) -Juliusサービスプロバイダのポート番号(デフォルト7500) -Juliusモジュールのポート番号(デフォルト10500) -Juliusのadinnetポート番号(デフォルト5530) -Juliusの実行ファイルの場所 -Juliusの設定ファイルの場所 これらのポート番号はJuliusで設定されているデフォルトのポート番号の値に設定されています。これらの値を先ほど設定したポート番号に変更します。 JULIUS_MODULE_PORT=10500 JULIUS_ADINNET_PORT=5530 ↓ JULIUS_MODULE_PORT=10511 JULIUS_ADINNET_PORT=10522 次にJuliusサービスプロバイダのポート番号を重複しにくい番号に変更します。 SERVICE_PORT=7500 ↓ SERVICE_PORT=10533 次にJulius設定ファイルの場所を変更します。 JULIUS_CONFIG_FILE=/usr/local/share/dictation-kit-v4.0/fast.jconf ↓ JULIUS_CONFIG_FILE=/home/<username>/dictation-kit-v4.0/fast.jconf また、これらのポート番号や設定ファイルはsigjsp.shの実行時に指定することもできます。何も指定しなければ上記の設定ファイルで指定した値になります。 % sigjsp.sh [-p <number>] [-sp <number>] [-mp <number>] [-ap <number>] [-e <path>] [-C <config.jconf>] OPTION : -p <number> : シミュレーションサーバのポート番号 -sp <number> : Juliusサービスプロバイダのポート番号 -mp <number> : Juliusモジュールモードポート番号 -ap <number> : adinnetポート番号 -e <path> : Juliusの場所 (デフォルト: /usr/local/bin/julius) -C <config.jconf;> : Juliusの設定ファイルの場所 これで設定は完了です。Juliusが正常に起動することを確認してください。 ***(null)と表示されてしまう場合 [#yc262c9c] juliusの設定ファイルfast.jconfに以下の一行を追加して実行してみてください。 ***音声認識結果が(null)と表示されてしまう場合 [#yc262c9c] Juliusの設定ファイルfast.jconfに以下の一行を追加して実行してみてください。 -charconv EUC-JP UTF-8 **音声データ(マイクからの入力)の音声認識 [#w8e9ffc0] 次にマイクで録音した音声データをSIGVerseで音声認識する方法を説明します。 ※クライアントpcにマイクが接続されていることが前提となります。 ***コントローラ編集 [#a43d5b9a] 先ほど作成したコントローラsoundRecog.cppを編集します。 $ cd ~/sigverse-<version>/bin/NewWorld $ emacs soundRecog.cpp #highlight(cpp:firstline[38]){{ // 音声認識結果を表示します。 const char * str = text->getString(); LOG_MSG(("text : %s", str)); }} の下に以下のコードを追加します。(これがなくても音声認識はできます) #highlight(cpp:firstline[41]){{ if(strstr(str, "こんにちは")) { // 自分自身を得ます SimObj *my = getObj(myname()); // 手を挙げます。 my->setJointAngle("RARM_JOINT2", DEG2RAD(90)); } }} これは「こんにちは」という認識結果が得られた場合に手を挙げるというものです。 それではコンパイルして実行してみましょう。 $ make ***録音した音声データの認識 [#ycb258d6] シミュレーションサーバを起動します。 $ ./sigserver.sh -p 9001 -w soundRecog.xml & Juliusを起動します。 $ ./sigjsp.sh -p 9001 次にSIGViewerを起動してサーバに接続し、先ほどと同様にシミュレーションを開始し、右上のcommタブをクリック、voiceを選択、送信対象者指定します。そして"Rec Start"ボタンをクリックして録音を開始します。 #ref(sound_2.jpg) マイクに向かって「こんにちは」としゃべってみてください。録音が終わったら"Rec End"ボタンをクリックします。この時SIGViewerの左下に「captured voice save to (Capture.wav)と表示されたら正常に音声データは録音されています。 #ref(sound_3.jpg) 次に"Send Voice"ボタンをクリックして先ほど録音したCapture.wavを選択します。先ほどのサンプルファイルsample.wavと同じ場所にCapture.wavが作成されています。 「こんにちは」と音声認識されればロボットが手を挙げると思います。ロボットが手を挙げるまでチャレンジしてみてください。 #highlight(end) //**他のエージェントへ音声データ送信 [#b4d2b5db] Up:[[Tutorial]] Previous:[[エージェント間のメッセージのやりとり]] Next:[[視覚に関する操作]]