Androidアプリ開発入門 (4) - TextToSpeech
Androidアプリでの「TextToSpeech」による「音声合成」の実装方法をまとめました。
・API 31: Android 12 (S)
前回
1. TextToSpeech
「音声合成」を実装するには、「TextToSpeech」を使います。
2. AndroidManifest.xml
Android 11(API Level 30)を対象とするアプリの場合、音声合成を利用するには、以下の要素を追加する必要があります。
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
3. 音声合成
コードは、以下のように記述します。
package net.npaka.texttospeechex
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.speech.tts.TextToSpeech
import java.util.*
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
private var tts: TextToSpeech? = null
// 起動時に呼ばれる
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
this.supportActionBar?.hide()
// TextToSpeechの生成
this.tts = TextToSpeech(this, this)
}
// TextToSpeechの初期化完了時に呼ばれる
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
// ロケールの指定
val locale = Locale.JAPAN
if (this.tts!!.isLanguageAvailable(locale) >= TextToSpeech.LANG_AVAILABLE) {
this.tts!!.language = Locale.JAPAN
}
// 音声合成の実行
this.tts!!.speak("こんにちは", TextToSpeech.QUEUE_FLUSH, null, "utteranceId")
}
}
}
処理の流れは、次のとおりです。
(1) TextToSpeechの生成。
(2) TextToSpeechの初期化完了時にonInit()が呼ばれる。
(3) 日本語ロケールの指定。
(4) 音声合成の実行。
4. ロケールの指定
ロケールを指定する前に、isLanguageAvailable()で可能かどうかを確認します。
・LANG_COUNTRY_VAR_AVAILABLE (2) : 言語がロケールで指定された通りに使用できる。
・LANG_COUNTRY_AVAILABLE (1) : 言語がロケールで指定された言語と国で使用できるが、バリアントで使用できない。
・LANG_AVAILABLE (0) : 言語がロケールによってその言語で使用可能であることを示すが、国およびバリアントでは使用できない。
・LANG_MISSING_DATA (-1) : 言語データが欠落している。
・LANG_NOT_SUPPORTED (-2) : 言語がサポートされていない。
5. 音声合成の実行
音声合成の実行には、speak()を使います。
int speak (CharSequence text, int queueMode, Bundle params, String utteranceId)
・text : テキスト (文字数はgetMaxSpeechInputLength()以下)
・queueMode : キューイング
・QUEUE_ADD : キューの最後にリクエストを追加
・QUEUE_FLUSH : キュー内のリクエストを削除し、新リクエストを実行
・params : パラメータ
・Engine#KEY_PARAM_STREAM : オーディオストリーム
・Engine#KEY_PARAM_VOLUME : 音のボリューム
・Engine#KEY_PARAM_PAN : 音の定位
・utteranceId : 発話ID
・戻り値 : 結果
・SUCCESS : 成功
・ERROR : 失敗
◎ オーディオストリーム
オーディオストリームを指定します。
・STREAM_ALARM : アラーム
・STREAM_DTMF : DTMFトーン
・STREAM_MUSIC : ミュージック
・STREAM_NOTIFICATION : 通知
・STREAM_RING : 電話呼び出し音
・STREAM_SYSTEM : システムサウンド
・STREAM_VOICE_CALL : 通話
◎ 音のボリューム
音のボリュームを(無音)0〜1(最大)で指定します。
val params = Bundle()
params.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, 0.7f )
◎ 音の定位
音の定位を(左)-1〜1(右)で指定します。
val params = Bundle()
params.putFloat(TextToSpeech.Engine.KEY_PARAM_PAN, 1.0f)
6. 音声合成のリスナー
「UtteranceProgressListener」を使うことで、音声合成の発話に関するイベントを受け取ることができます。
this.tts!!.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
override fun onStart(utteranceId: String) {
Log.d("debug","onStart")
}
override fun onDone(utteranceId: String) {
Log.d("debug","onDone")
}
override fun onError(utteranceId: String) {
Log.d("debug","onError")
}
})
主なメソッドは、次のとおりです。
onStart(utteranceId: String!)
発話を開始した時に呼ばれる。
onStop(utteranceId: String!, interrupted: Boolean)
発話が停止された時に呼ばれる。
onDone(utteranceId: String!)
発話が正常に完了した時に呼ばれる。
onError(utteranceId: String!)
onError(utteranceId: String!, errorCode: Int)
エラー時に呼ばれる。
onAudioAvailable(utteranceId: String!, audio: ByteArray!)
オーディオの準備完了時に呼ばれる。
onBeginSynthesis(utteranceId: String!, sampleRateInHz: Int, audioFormat: Int, channelCount: Int)
utteranceIdの発話の開始時に呼ばれる。
onRangeStart(utteranceId: String!, start: Int, end: Int, frame: Int)
utteranceIdの発話の指定範囲を読み上げる時に呼ばれる。
7. 声の指定
setVoice()をTTS初期化後に呼ぶことで、声を指定することができます。
tts!!.setVoice(voice)
指定可能な日本語の声の一覧は、以下のコードで取得できます。
for (voice in tts!!.voices) {
if (voice.name.startsWith("ja")) {
Log.d("debug", voice.name)
}
}
ja-JP-language
ja-jp-x-jab-network
ja-jp-x-htm-network
ja-jp-x-jad-network
ja-jp-x-jac-network
ja-jp-x-jab-local
ja-jp-x-jad-local
ja-jp-x-jac-local
ja-jp-x-htm-local
8. 声の速度と高さの指定
setSpeechRate()とsetPitch()をTTS初期化後に呼ぶことで、声の速度と高さを指定することができます。
・声の速度 : 1.0は通常、0.5 : 通常の半分、2.0 : 通常の倍
・声の高さ : 1.0は通常、値小 : 低い声、値大: 高い声
tts!!.setSpeechRate(1.2f)
tts!!.setPitch(0.8f)