FC2ブログ

スマフォのアプリを作りたい(27):スマフォだけで動作する音声認識③

   プログラミング [2020/07/09]
JuliusをAndroidスマフォ上で動作させたいと思ってます。
概ね
Ⅰ.まずはJavaコードからC関数を呼び出すようなアプリの作り方を調べます。
Ⅱ.Javaコード(Cライブラリ含む)をReact Nativeで使えるパッケージ化方法を調べます。
Ⅲ.React Nativeにパッケージを取り込んで、Build&Go。
の順番かと思ってますが、現状は未だの途中です。

前回、AndroidStudioでC++のプロジェクトを作成して、テンプレートを動作させました。
それと、Juliusのライブラリ使用のサンプルjulius-simple.cをちょっと俯瞰してみました。

その続きです。


◆続:AndroidStudio環境へのJuliusLib移植
前回julius-simple.cを見ていて気になる点が2つほどありました。
※1:標準出力を使っている。→Androidでは?
※2:音声データの入力方法に「バッファ渡し」的なものはない。

※1の件に関しては調べだしたらすぐ解決しました。
Androidでは標準出力はlogcatになっている(標準エラー出力も含む)そう。
訂正:誤報です。標準出力がだまっててもlogcatに出力されるわけではありませんでした。
詳細は次回に記載いたします。m(__)m


「では、MIC入力は?」とも思いますが、
動き出せたら、Juliusがエラー等のメッセージを出力してるでしょうから、きっと対策の糸口は見えるかと。


AndroidStudioのC++テンプレートでのJavaからC関数のコールのところがまだモヤモヤです。
もうちょっと深追いが必要です。
参考:https://qiita.com/ymmtyuhei/items/7109579210af34ec697c

JNI(Java Native Interface):Javaとネイティブコードとのインタフェース仕様のことだそうです。
呼び出し元のJavaでstringFromJNI()とされている関数名が、呼び出し先で酷く長い関数名になっていたのは、この仕様によるもののようです。
native-lib.cppで定義されていた関数名の形式・意味は、以下だそうです。

Java_[呼び出し元のパス(src後のパス&“_”区切り)とファイル名(拡張子なし)]_呼び出し関数名()

なので、stringFromJNI()
Java_com_teburarec_call_1julius_MainActivity_stringFromJNI()になるわけです。
途中のcall_juliusと言うフォルダがcall_1juliusと表現されているのは、区切り記号としての「_」とフォルダ名中の「_」を区別するためなんだろうなと思います。


では、移植作業を始めましょう。
上記の参考サイトが参考にしている本家サイトの説明を読んでみます。
参考:https://developer.android.com/studio/projects/add-native-code?hl=ja

まずはソースを作成/追加しろと書かれています。


1)JuliusLibのソースの持ち込み
Juliusサイトからダウンロードしてきたディクテーションキットに含まれるソースからコピーします。
dictation-kit-4.5\src\julius-4.5フォルダ下のlibjulius、libsentをフォルダごとAndroidStudioのプロジェクトフォルダにコピーします。
コピー先:(プロジェクトフォルダ)\app\src\main\cpp ・・・・native-lib.cppのあるフォルダ


2)native-lib.cppへのjulius-simple.c内処理のマージ
2-1)julius-simple.c内の「#include ・・・」から内部関数をnative-lib.cppの「#include ・・・」の下にコピペしました。
2-2)julius-simple.c内のmain()の処理コードをcom_teburarec_call_1julius_MainActivity_stringFromJNI()の処理コードにまるっと置き換えました。

この時点で、AndroidStudio側で、native-lib.cppを開くと、自動的に静的解析(って云うんでしょうか)が行われているようで、辻褄の合わない箇所がエラーとして表示されます。(変な箇所が赤字で表示されて、ポインタを載せるとエラーの内容が表示されます。)

まずは、先頭の「#include 」で、「そんなパスは存在しない。」と出ます。
なので、それ以降のライブラリのヘッダに含まれる定義(変数、定数、関数)が全部未定義のものというエラーです。

早い話、JuliusLib用のインクルードパスをどっかで指定しないといけないですね。

先の本家ページの次の手順がCMakeを設定しろなので、設定の仕方を調べました。
CMakeの設定は、CMakeList.txtで行うんですね。
native-lib.ccppと同じフォルダ:(プロジェクトフォルダ)\app\src\main\cppにありました。

3)CMakeList.txtの編集
3-1)CMakeList.txtでインクルードパスを指定します。
以下の朱書きの記述を追加しました。
----CMakeList.txt---------------------------------

add_library( # Sets the name of the library.
native-lib


native-lib.cpp )

# インクルードパス指定
target_include_directories( # ターゲット名
native-lib
# Private指定
PRIVATE
# インクルードパス
${CMAKE_CURRENT_SOURCE_DIR}/libjulius/include
${CMAKE_CURRENT_SOURCE_DIR}/libsent/include
)



---------------------------------------------------


さらに、-Dコンパイルオプションで振り分けされているインクルードファイルがあるらしく、その中で定義されている定数も未定義となっていました。

3-2)CMakeList.txtでコンパイルオプション(-D)を指定する。
以下の記述を追加しました。
----CMakeList.txt---------------------------------
# コンパイル オプション指定
option(__ANDROID__ "for Android" ON)
if(__ANDROID__)
add_definitions(-D__ANDROID__)
endif()

---------------------------------------------------



4)native-lib.cppの修正
この時点で残ったエラーは、元のjulius-simple.cのmain()からそのままコピペした部分でした。

・引数(argc,argv)の参照がそのままになっている点
 →引数の問題は、参照部分削除/固定値の参照に変更
  const int argc = 3;
  const char *argv[] = {"julius-simple", "-C", "simple_keyword.jconf"};

・char * を指定するべき引数に、const char *を指定していると警告
 「jconf = j_config_load_args_new(argc, argv);」を
 →「jconf = j_config_load_args_new(argc, (char **) argv);」に変更
 「while (get_line_from_stdin(・・・, "enter MFCC filename->") != NULL) {」を
 →「while (get_line_from_stdin(・・・, (char *) "enter MFCC filename->") != NULL) {」

・リターンが数値になっている点・・・元のテンプレートは文字列(ポインタ)
 →「return env->NewStringUTF("メッセージ");」に変更

としました。

-ちょっとハマった:静的解析機能の混沌-
これで、ひとまずjulius-simple.cベースのnative-lib.cppのフラグはとれた。・・・かと思いきや。

何回かCMakeList.txtや、ソースコードをAndroidStudioで書き換えてたのですが、最初のころは書き換えた時点でAndroidStudioが新しい内容で再チェックするような動きをしてました。ですが、その内チェックし直さないようになりました。エラーが消えません。その場合は、エラー個所にカーソルを置いて、[Alt]+[Enter]を押すと赤字表示が赤以外に変化して「問題ない」状態を表してました。

さらに、最初にエラーが消えたと思った、「#include 」が、何かの拍子に再度エラーに復活した。おかげでコードの中で使っているヘッダで定義されているものが全部赤表示に戻りました。

ただしこの段階でビルドした場合は、同様のエラー(インクルード・ヘッダが Not Found)にはならなかった。
つまり、Inspection機能(以降、静的解析と呼んじゃいます。)だけの問題のようです。

最初から出てたのかもしれませんが、AndroidStudioの上部に「Unable to execute Clang-Tidy: Cannot create property=Diagnostics for JavaBean=com.jetbrains.cidr.lang.daemon.clang.tidy.ClangTidyYamlLoader...」というエラーが表示されっぱなしです。ClangTidyはコードチェックツールらしいので、修正結果を自動で更新チェックしなくなった件と関係するんでしょうか。
上記したメッセージは放置しても構わないのか?とも思ったのですが、メッセージの後ろに「設定」が行えるリンクが貼られていたので、クリックしてClang-Tidyの有効?チェックを外したらメッセージは消えた。でも正しい処置とは思えない。注1)

それでも、静的解析の#includeに絡む警告は消えません。

「Unable to execute・・・」の件を調べましたが、AndroidStudio3.5とNDK r21では互換性がない?とかの書き込みがあって、AndroidStudio4.0では対策されているとありました。調べたら、その条件に当てはまりました。注2)
ちょっと身も蓋もない話で俄に信じがたい感じですが、Clang-Tidyのチェックを外したのは正解かも。

Clang-Tidyと切り離して、さらにググりましたが、なかなか解が見つかりません。
そんなこんなしている間に、AndroidStudioを一旦終了(PCの再起動を含む)し、再起動したら・・・
あれ?エラー表示が消えました。何で?


以下の参考サイトを見つけて、能動的に静的解析を実行することを考えていたのですが、肩透かしに会いました。注3)
参考:https://gihyo.jp/dev/serial/01/android_studio/0040


注1)Clang-Tidyを有効に戻す手順は
 -[File]-[Settings...]選択
 -左側リスト欄の「Editor」を展開し、Inspectionsを選択
 -右(中)側のリストから「C/C++」を展開
 -「Gerenal」-「Clang-Tidy」をチェックし、右下の[OK]をクリック

注2)AndroidStudioのバージョン確認は、メニュー[Help]-[About]
 NDKのリビジョンの確認手順は
 -メニュー[Tools]-[SDK Manager]選択
 -右側欄の「SDK Tools」タブを選択
 -右下の「Show Package Details」をチェック
 -「NDK(Side by side)」の下でチェックされているのがそれ

注3)Inspectionの実行は、
 -[Analyze]-[Isnpect Code...]選択
 -チェックする範囲(プロジェクト全体、単独ファイル等)を選択し実行
 -[Inspection Result]タブが画面下に作成される



CMakeList.txtで指定したインクルードパスが有効にならなかった件は放置して、本家サイトに書いてある3番目のGladleを設定しろをやってみます。

・・・

続きを読む

スポンサーサイト





カレンダー
06 | 2020/07 | 08
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 -
プロフィール

さるもすなる

Author:さるもすなる
さるです。別HPサイト「さるもすなる」から侵食してきました。 山菜/きのこ、それとタイトルにしたPPバンド籠のことをメインに徒然に・・・・暇を持て余したさるの手仕事:男手芸のブログってことで。

最新記事
最新コメント
月別アーカイブ
カテゴリ
天気予報

-天気予報コム- -FC2-
本家のHPのトップ
山菜や茸の話です
PPバンドの籠作品と作り方です
投稿をお待ちしております



PVアクセスランキング にほんブログ村 にほんブログ村 ハンドメイドブログへ



マニュアルのお申し込み



検索フォーム
リンク
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QR