2017/10/11

BLEデータに応じて音声合成で読み上げ!

どうも、クラゲです。
今回は、BLEデバイスからNotifyで読み込んだデータに応じて読み上げを行う方法です。
音声ファイルは不要! 指定したテキストを音声合成で読み上げます。例えば、センサーの値を読み上げるなどの応用に使えます。

動画の音声はONにして見てください。今回も半固定抵抗のツマミを人が回すことで、センサー値の変化を代用しています。ツマミを回して、ある程度値が落ち着いたところで読み上げているのが分かると思います。

【 必要なもの 】

scan のときと同じです

【 デモページとソースコード 】

デバイスがBLE Nanoの場合で説明します。
半固定抵抗のツマミを回すことで音声を出力することが出来ます。

WEB上で試せるデモページはこちら
https://secure1689.sakura.ne.jp/kurage.jellyware.jp/bluejelly/advance_speech.html

ローカル環境で試したい方はこちらのGitHubからダウンロードし、advance_speech.htmlを実行してください。
https://github.com/electricbaka/bluejelly

プログラムのベースはnotify です。
では、早速読み上げ追加部分について見てゆきましょう

【 プログラム解説(HTML) 】

HTMLは特に追加変更部分はありません!

【 プログラム解説(JavaScript) 】

音声合成を使うために、最初にインスタンス生成と言語設定が必要です

var speech = new SpeechSynthesisUtterance();//インスタンス生成
speech.lang = 'ja-JP';//言語の設定

例えば、"こんにちは"を音声合成で読み上げる場合は、以下の記述のみでOKです。

speech.text = "こんにちは";
speechSynthesis.speak(speech);

これをそのままvalueに置き換えれば使えそうですね。
しかし、onRead部において"こんにちは"の代わりにvalueにすると、値を読み上げますが、notifyによりデータをずっと連続で受信しているため、読み上げが止まらなくなってしまいます。
そこでクラゲは以下の3つの工夫を追加しました。

それでは見て行きましょう

読み上げキャンセルは簡単です。speakメソッドの前にcancelメソッドを行うだけです。

speechSynthesis.cancel();
speechSynthesis.speak(speech);

読み上げのタイミングを遅らせる方法は、setTimeoutを使って実現しています。clearTimeoutでタイマーをリセットしています。Global部にてtimer_idという変数を用意して、タイマーを管理しています。
speech_laterという関数を作り、先ほどの2行の処理(cancelとspeak)を行っています。

if(value != old_value)
{
  old_value = value;
  speech.text = value;
 
  clearTimeout(timer_id);
  timer_id = setTimeout(speech_later,500);
}

前回と同じ値になったら読み上げ確定を行う処理も、上記のプログラムにif文で記述されています。なお、Global部にold_valueという変数を用意して、前回の値を管理しています。

いかがでしょうか?
画面が見れないような環境で値を読み上げてくれると色々と便利な使い方も思いつくかもしれません!

以上、BLEデータに応じて音声合成で読み上げでした。