Phonetica (Receiver)

Receiverモード
Phoneticaメインビュー下部にあるタブバーよりReceiverモードへと切換られる.
Receiverモードのメインビュー
これは通信ごっこをする時に,受信者が使うモードである. まずは画面下部に位置するモールスコード用ソフトウェアキーボードについて説明する. "."ボタンをタップすると画面中央やや上の藍色テキストフィールドにDot"."が表示される. 続いて"-"ボタンをタップしてみる. するとテキストフィールドには".-"という文字列(コード列)が表示される. これはモールスコードで,英字の"A"に対応する. よって,ここで"Enter"ボタンをタップすると,Resultウィンドウにその結果"A"が表示される.
この状態で"Enter"をタップすれば文字列"PHONETICA"が結果として表示される.
また,送信者がメールに貼り付けて送信してきたモールスコード(DotsとDashesと空白)を直接藍色のテキストフィールドに貼り付けて,iOSキーボードの"return"キーをタップしても逆変換された結果が表示される. 結果をタップするとアクションシートが現れ,クリップボードへのコピーが出来る.
"Copy"をタップすると,結果がクリップボードへとコピーされる.
なお,結果の一番後ろに付いているアンダーバー"_"はカーソル位置を示している. 単語間などに空白が必要ならば"Space"キーをタップ. コードの入力を間違った場合には"Del"キーをタップすると一文字分削除する. もし,藍色テキストフィールドに何も入力が無ければ,結果から一文字分が削除される.

受信機にはカメラによる受信機能が付されている. "Camera"ボタンをタップすると起動する. なお,カメラの無いiOSデバイスではこのボタンは表示されない. あしからず.
カメラ受信機能の起動画面
この画面で"Receive"ボタンをタップすればカメラによる受信が開始される. ところで,カメラを使って何を受信するのかと言えば,Senderモードで紹介した,フラッシュライトによるモールスコードである. 相手(送信者)がフラッシュライトにより送信してきたモールスコードを,自分(受信者)がカメラにより受信,この受信した信号を復号して元の平文(英文)を得られるわけである. ある種の光通信である. さて,"Receiver"ボタンをタップすると下の様な画面へと遷移する.
"円を送信者へ向ける"と書いてある.
3秒の待ち時間の後,信号を受信出来る状態となる. 待っている間の3秒間は送信者側のフラッシュライトが発光していないことが望ましい. また,この3秒間で,画面中央の円(照準)を送信者側iOSデバイスのフラッシュライトへ向けること. 照準はあまり動かさぬこと. 暗い所,または背景が黒い所なら認識精度が向上する. 理由については,次章の"技術的背景,おもにアルゴリズム"を参照されたい. このプログラムは円内(照準内)の輝度値のみを取得しているので受信中に相手のフラッシュライトが円から外れると正しく受信出来ない. 受信可能状態となると画面上部に"Receiving"と表示される. また正しく光りを受信できていれば,照準が緑色へと変化すると同時に,受信したモールスコードが照準のすぐ上に表示される. 信号をすべて受信出来たと思ったら"Done"ボタンをタップする. すると下のようにアラートが表示される.
フラッシュライトの点滅により"D"を得られた.
"Copy"をタップすれば受信結果をクリップボードへコピー出来る. "Done"をタップすると何もせずに終了する. 例では"D"という文字のみを受信したが,もっと沢山の文字列を一度に受信することも可能である. ただし,受信可能時間は60秒のみ. 受信可能状態となって60秒経過すると,勝手に受信完了とみなされる. この場合,終了10秒前にその旨のメッセージが表示されるようになっている.

技術的背景おもにアルゴリズム
モールスコードから英数字への変換は,Senderモードで紹介した英数字からコードへの変換処理とほぼ同じ仕組を採用している. 3つの辞書と共通のインデックスを用いる方法だ. 詳細は前回の記録を参照. 違いは,英数字は1文字が1つのモールスコードへ対応していたのに対し,モールスコードはDotsやDashesといった複数文字が1つの英数字に対応している点であろう. モールスコードは対応する英数字によりコード長が違うのでfor文だけを使ってひとつのまとまったコードを取得することが難しい. 幸い,コード間には空白が設けられている. まずはfor文でこの空白を探す. 空白が見つかったらコード文字列先頭から,その空白が見つかった位置までの文字列を抜き取る. それをcurrentCodeなる変数へ代入する. 後は順変換と同じ仕組で逆変換をするだけである. なお,この方法だと一番最後のコードにて空白が見つからずにエラーが発生してしまうので,入力文字列(コード列)を取得すると同時に,文字列後尾に空白をひとつ結合しておく必要がある点に注意.

カメラによるコード受信は,輝度値の変化を取得することで実現した. 画面中央,およそ30x30ピクセル分(正方形)の輝度値を,ほぼリアルタイムに取得している. 表示されている照準(円)はあくまで目安である. iOSデバイスのカメラから取り込んだ画像をビットマップ化して配列に代入,この時配列にはRGBA8888形式で代入されるようにした. 各ピクセルの赤,緑,青の割合を重み付けして加算することで輝度値としている. 赤緑青はそれぞれ0~255の値をとりうる. それらを次のように重み付け加算した.
$$ luminance = red*0.299 + green*0.587 + blue*0.114; $$
これはNTSC方式映像の輝度値と同じである. つまり,その映像が白ければ白いほど明るいと認識するのである. 結果,輝度値を表す変数luminanceは0~255の値をとりうることとなり,この値の変化を監視してライトの点滅を認識している. 待ち時間の3秒間で,その場所の環境光を取得している. 精確には最後の1秒間の輝度値の変化をすべて取得し,フレーム数で除して環境光の平均値を取得している. この平均値+αの値を閾値として設定,閾値以上の輝度値を認識したら,それはフラッシュライトの点灯と認識される. フラッシュライトが点灯したらその時の時刻を取得する. フラッシュライトが消灯したら先に取得した時刻と現在の時刻との差分を取得する. 差分がおよそ0.2秒,すなわち1Unit分であったならDot".",3Units分であったならDashes"-"であると認識する. およそというのも,カメラのフレームレートやら環境光の変化やらにより多少の誤差が生ずるので,その誤差を踏まえて識別するためである. 今回は±0.09秒の誤差を認めた. 消灯についても同じ仕組である. 1Unit分ならばコードの途中,3Units分ならば文字間,7Units分ならば単語間であると認識する. このように一文字ずつコードを取得,結果へ結合して行き,"Done"ボタンがタップされたのを合図に,受信結果のコードを復号(逆変換)する. その後すべての変数を初期化している.

以上でPhoneticaのだいたいの説明は終えた. 気になることがあれば心を楽にして質問して欲しい. 間違いの訂正や補修依頼も歓迎である.
4287390206655706669 http://www.storange.jp/2013/08/phonetica-receiver.html http://www.storange.jp/2013/08/phonetica-receiver.html Phonetica (Receiver) 2013-08-29T09:38:00+09:00 http://www.storange.jp/2013/08/phonetica-receiver.html Hideyuki Tabata 200 200 72 72