スマフォのアプリを作りたい(32):スマフォだけで動作する音声認識⑦
プログラミング [2020/09/09]
前回の続きになります。
でも、だいぶ間があいちゃいましたね。
前回割と中途半端なところで話を切ったので、この回から読み始めても「さっぱり何言ってんのかわかんない」と思います。
(それじゃなくても、独り言に近い備忘録なので、他の人が読んでもどうにか理解できるのかはあまり気に掛けてません。)
なので、もし類似の何かを調べしている方は、
「スマフォだけで動作する音声認識⑥」から、あるいは「スマフォだけで動作する音声認識①」からお読みください。
前回までで、JavaからC/C++のライブラリをコールして、さらにライブラリ側からJava側のコールバックを呼び出すところまでを実験的にやってみました。
今回は、今までの内容を整形(コードをそれなりの内容にまで整える)して、さらにReact Native用パッケージに仕立てるところ・・・
行けるかどうか分かりませんが、始めます。
◆単語認識ライブラリのコールバックの実装
ず~~~っと前に作ったGoogle音声認識と同時に録音するJavaコード(さるもすなる版react-native-google-speech-api)では、音声データをバッファで渡すことができます。
データ型はbyte配列(byte[])です。
ただし、そのバッファを握ったまま音声認識の処理が終わるまで離さないということは、どう考えても効率が悪そうだし、そんな制御は却って難しそうです。
なので、認識を開始した後に渡す音声データは、コールバックで渡す段階で認識側専用のバッファ(char *の先)にデータをコピーするのがまあ普通な考え方かと。
じゃあ、そのコピーはJava側で行うのか、C側で行うのか・・・
Java側でやるなら、
Java側にC側で用意したバッファのポインタをそのまま渡せるのか?できない?
前回記事でお試しコードを書いたときは、わざわざJavaのbyte型配列を新しく確保して渡した。
これだと、データコピーが2回発生してしまう。
C側でコピーするとしたら
Java側のコールバック関数のリターン値をデータアドレスとデータ長の2種類を含むものにしないといけなくなる。
①C言語でいうところの参照型の引数を使ってJava側のバッファアドレスを貰って来ることはできるのか?
②バッファを渡した側がデータのコピーの完了を知る術がない(そのバッファの解放判断ができない)んじゃない?
①:そもそも、Javaにポインタという概念はないらしい。
byte[]型のオブジェクトそのものはリターン値として使えて、そこから中身のレングスとポインタはJNIの関数で取り出せるみたいです。
②:でもでも、リターンのタイミングでそれを渡したとすると、コピーの完了を知るすべがないということになります。
Java側のバッファの「用済み」がいつなのか分からないと、バッファを解放できないということになります。
データコピーの完了を知らせるために別の仕掛けを用意しなくちゃいけなくなってしまいます。
認識が完了するまで、Java側バッファも保持しつづける?
それは、後々厄介なことになりそう。
悩んだ末に、こんなことを考えました。
Javaのコールバックを呼ぶんだけど、そのコールバックは再度C関数を呼び出して、そのC関数がデータのコピーをやっちゃうって仕掛けです。
まずは、やってみました。
ここでも結局、Java側のコールバック関数を経由して、C側のバッファのポインタはどう渡すんだ?
と、振り出しに戻るような疑念が出ました。
結局そこはC側にグローバル変数を用意して、自分のバッファとその長さを保持して
コールバックから呼ばれたデータコピー関数は、グローバル変数を参照することで、済ませてしまいました。
かなりベタというか、美しくありません。
これだと、マルチスレッドでこのコールバック処理が非同期に実施されるようなことがあれば、アウトです。
ともあれ、この作りで一旦先に進みます。
続きます。この後も長ーいです。
でも、だいぶ間があいちゃいましたね。
前回割と中途半端なところで話を切ったので、この回から読み始めても「さっぱり何言ってんのかわかんない」と思います。
(それじゃなくても、独り言に近い備忘録なので、他の人が読んでもどうにか理解できるのかはあまり気に掛けてません。)
なので、もし類似の何かを調べしている方は、
「スマフォだけで動作する音声認識⑥」から、あるいは「スマフォだけで動作する音声認識①」からお読みください。
前回までで、JavaからC/C++のライブラリをコールして、さらにライブラリ側からJava側のコールバックを呼び出すところまでを実験的にやってみました。
今回は、今までの内容を整形(コードをそれなりの内容にまで整える)して、さらにReact Native用パッケージに仕立てるところ・・・
行けるかどうか分かりませんが、始めます。
◆単語認識ライブラリのコールバックの実装
ず~~~っと前に作ったGoogle音声認識と同時に録音するJavaコード(さるもすなる版react-native-google-speech-api)では、音声データをバッファで渡すことができます。
データ型はbyte配列(byte[])です。
ただし、そのバッファを握ったまま音声認識の処理が終わるまで離さないということは、どう考えても効率が悪そうだし、そんな制御は却って難しそうです。
なので、認識を開始した後に渡す音声データは、コールバックで渡す段階で認識側専用のバッファ(char *の先)にデータをコピーするのがまあ普通な考え方かと。
じゃあ、そのコピーはJava側で行うのか、C側で行うのか・・・
Java側でやるなら、
Java側にC側で用意したバッファのポインタをそのまま渡せるのか?できない?
前回記事でお試しコードを書いたときは、わざわざJavaのbyte型配列を新しく確保して渡した。
これだと、データコピーが2回発生してしまう。
C側でコピーするとしたら
Java側のコールバック関数のリターン値をデータアドレスとデータ長の2種類を含むものにしないといけなくなる。
①C言語でいうところの参照型の引数を使ってJava側のバッファアドレスを貰って来ることはできるのか?
②バッファを渡した側がデータのコピーの完了を知る術がない(そのバッファの解放判断ができない)んじゃない?
①:そもそも、Javaにポインタという概念はないらしい。
byte[]型のオブジェクトそのものはリターン値として使えて、そこから中身のレングスとポインタはJNIの関数で取り出せるみたいです。
②:でもでも、リターンのタイミングでそれを渡したとすると、コピーの完了を知るすべがないということになります。
Java側のバッファの「用済み」がいつなのか分からないと、バッファを解放できないということになります。
データコピーの完了を知らせるために別の仕掛けを用意しなくちゃいけなくなってしまいます。
認識が完了するまで、Java側バッファも保持しつづける?
それは、後々厄介なことになりそう。
悩んだ末に、こんなことを考えました。
Javaのコールバックを呼ぶんだけど、そのコールバックは再度C関数を呼び出して、そのC関数がデータのコピーをやっちゃうって仕掛けです。
まずは、やってみました。
ここでも結局、Java側のコールバック関数を経由して、C側のバッファのポインタはどう渡すんだ?
と、振り出しに戻るような疑念が出ました。
結局そこはC側にグローバル変数を用意して、自分のバッファとその長さを保持して
コールバックから呼ばれたデータコピー関数は、グローバル変数を参照することで、済ませてしまいました。
かなりベタというか、美しくありません。
これだと、マルチスレッドでこのコールバック処理が非同期に実施されるようなことがあれば、アウトです。
ともあれ、この作りで一旦先に進みます。
続きます。この後も長ーいです。
スポンサーサイト
嬉し恥ずかしお百姓Season2(20):原野草刈り
園芸 [2020/09/06]
毎週実家の畑に通って、農作業の真似事をするのですが、
5~6割くらいは、畑(原野になってる部分含む)の草刈り作業です。
草刈り機の燃料(混合ガソリン)は、4L缶で今年既に4本目になってます。
草を刈る手間を省くために、畑に復活させて、何等か作付けしているのですが、
却って、草を刈る頻度は増えました。
なぜかって、やらないと、植えた作物の成長に関わるし、見栄えが悪いから。
なので、未だ原野化した部分の草刈りまでなかなか手が回りません。
いつもなら、栗林の部分も終わっている時期なのですが、そこは未だ手付かずです。
さて、原野のままの部分(柿の木が植わっています。)の草刈り作業は、
さるの一行農業日誌によると、8/1にSTARTになってました。
この時点でこんな状態です。

ススキやヨモギ、ヨツバヒヨドリ、アザミなんかは、大人の背丈を越えてます。
この日、にわか雨まじりの天気でしたが、1日掛けて、ズブ濡れになりながら、
こんなくらいを刈りました。

この写真で見えてる後ろの方も刈ったので、原野部分はこれで1/3くらいの広さが終わったのみです。
その後・・・
5~6割くらいは、畑(原野になってる部分含む)の草刈り作業です。
草刈り機の燃料(混合ガソリン)は、4L缶で今年既に4本目になってます。
草を刈る手間を省くために、畑に復活させて、何等か作付けしているのですが、
却って、草を刈る頻度は増えました。
なぜかって、やらないと、植えた作物の成長に関わるし、見栄えが悪いから。
なので、未だ原野化した部分の草刈りまでなかなか手が回りません。
いつもなら、栗林の部分も終わっている時期なのですが、そこは未だ手付かずです。
さて、原野のままの部分(柿の木が植わっています。)の草刈り作業は、
さるの一行農業日誌によると、8/1にSTARTになってました。
この時点でこんな状態です。

ススキやヨモギ、ヨツバヒヨドリ、アザミなんかは、大人の背丈を越えてます。
この日、にわか雨まじりの天気でしたが、1日掛けて、ズブ濡れになりながら、
こんなくらいを刈りました。

この写真で見えてる後ろの方も刈ったので、原野部分はこれで1/3くらいの広さが終わったのみです。
その後・・・
嬉し恥ずかしお百姓Season2(19):エダマメ・パニック
園芸 [2020/09/05]
9月だというのに、まだ暑いですね。
北国ですが、信じられないくらい暑いです。
かと思えば、局地的大雨。
絶対、温暖化の影響だと思っているさるです。
7月の下旬に土寄せ作業をして、再度ほったらかしてたエダマメ(茶豆)の話です。
土寄せ作業をした時で、花が咲いていたのですが、3週間くらいで、エダマメの形状になってました。

割と実が付いてからが早いのね。
先々週、赤ソバの種蒔きの合間に、フラフラしながら生ったエダマメのサヤを触ってみると、それなりに実が入ってそうだった。
なので、10株くらい引っこ抜いておいて、

ソバ蒔き終わりに持ち帰った。
その時点でも、エダマメ畑は、こんな。

さる家だけでは、到底消費しきれないのは分かり切っていたので。
一族のものに、勝手に採って食べてくれと連絡しておいた。
翌朝、早起きして採ってきたエダマメの枝からエダマメを取ったら、大きなボール1杯くらいになった。
さっそく、茹でてもらって、三日掛けて食べた。
まだ、少し若い感じではあったが、十分食べられた。

で、先週末・・・
北国ですが、信じられないくらい暑いです。
かと思えば、局地的大雨。
絶対、温暖化の影響だと思っているさるです。
7月の下旬に土寄せ作業をして、再度ほったらかしてたエダマメ(茶豆)の話です。
土寄せ作業をした時で、花が咲いていたのですが、3週間くらいで、エダマメの形状になってました。

割と実が付いてからが早いのね。
先々週、赤ソバの種蒔きの合間に、フラフラしながら生ったエダマメのサヤを触ってみると、それなりに実が入ってそうだった。
なので、10株くらい引っこ抜いておいて、

ソバ蒔き終わりに持ち帰った。
その時点でも、エダマメ畑は、こんな。

さる家だけでは、到底消費しきれないのは分かり切っていたので。
一族のものに、勝手に採って食べてくれと連絡しておいた。
翌朝、早起きして採ってきたエダマメの枝からエダマメを取ったら、大きなボール1杯くらいになった。
さっそく、茹でてもらって、三日掛けて食べた。
まだ、少し若い感じではあったが、十分食べられた。

で、先週末・・・