N.Yamazaki's blog

主に音声合成について思ったことを書いてみようと思います。
<< 省RAM版の言語処理エンジンのプロトタイプ開発 | main |
「AquesTalk-ESP32 Ver.2.0」を使う

keywords:音声合成, 組み込み, 日本語, ESP32, M5Stack

 

 

 

■概要


AquesTalk-ESP32は、ESP32向けの音声合成ライブラリです。
これが今回バージョンアップしました。
また、Arduino-ESP32も大幅に変更されました。
そこで、新しくなったAquesTalk-ESP32の使い方を紹介します。

 

 

■これまでとの違い


AquesTalk-ESP32 Ver.2.0  ダウンロード

漢字が読めるようになりました。これまでは音声記号列からの音声合成でしたが、小型軽量になった言語処理エンジンAqKanji2Romanが組み込まれました。
数MBの言語辞書データは、SDメモリカードやシリアルフラッシュメモリなど、比較的低速な外部メモリに配置しながらも、高速に処理ができます。

 

Arduino-ESP32

2018/06/28に大規模な変更がありました。
インストール方法がArduino IDE のボードマネージャを使う方法に変わりました。
インストールされる場所も変更されています。
これに伴い、AquesTalk-ESP32ライブラリのインストール場所も変更が必要です。
また、I2S関連の関数も変更されていて、従来のコードでは2倍のサンプリング周波数で再生される不具合が生じています。

 


■ビルド準備 ArduinoIDEの場合


ArduinoIDEによる開発環境上に、AquesTalk-ESP32をセットアップする手順を以下に示します。
ArduinoIDEや、ArduinoIDEでESP32をビルドするための「Arduino core for the ESP32」は、すでにインストールされているものとします。


1.  次の場所にライブラリとヘッダをコピーします。

    {PATH_Arduino_ESP32}¥tools¥sdk¥lib¥libaquestalk.a
    {PATH_Arduino_ESP32}¥tools¥sdk¥include¥aquestalk¥aquestalk.h

ここで、{PATH_Arduino_ESP32}は、「Arduino core for the ESP32」がインストールされた場所です。 私の環境では次のとおりでした。

    C:¥Users¥{ユーザ名}¥AppData¥Local¥Arduino15¥packages¥esp32¥hardware¥esp32¥1.0.0

aquestalk¥aquestalk.hのaquestalkフォルダは作成してください。


2.  次の場所にplatform.local.txtを作成します。同じ場所にplatform.txtがあるはずです。

    {PATH_Arduino_ESP32}¥platform.local.txt

platform.local.txtには、以下を記述します。これは、コンパイル時のインクルードパスにaquestalkを追加し、リンク時にlibaquestalk.aを加える指定です。

compiler.c.extra_flags="-I{compiler.sdk.path}/include/aquestalk"
compiler.cpp.extra_flags="-I{compiler.sdk.path}/include/aquestalk"
compiler.c.elf.libs=-lgcc -lopenssl -lbtdm_app -lfatfs -lwps -lcoexist -lwear_levelling -lesp_http_client -lhal -lnewlib -ldriver -lbootloader_support -lpp -lmesh -lsmartconfig -ljsmn -lwpa -lethernet -lphy -lapp_trace -lconsole -lulp -lwpa_supplicant -lfreertos -lbt -lmicro-ecc -lcxx -lxtensa-debug-module -lmdns -lvfs -lsoc -lcore -lsdmmc -lcoap -ltcpip_adapter -lc_nano -lesp-tls -lrtc -lspi_flash -lwpa2 -lesp32 -lapp_update -lnghttp -lspiffs -lespnow -lnvs_flash -lesp_adc_cal -llog -lsmartconfig_ack -lexpat -lm -lc -lheap -lmbedtls -llwip -lnet80211 -lpthread -ljson  -lstdc++ -laquestalk

compiler.c.elf.libsの部分は、Arduino core for the ESP32のバージョンによって異なります。必ずplatform.txtからcompiler.c.elf.libsの部分をコピペして、最後に -laquestalk を加えます。

 

以上で準備は終わりです。

 


■AquesTalk-ESP32のラッパークラス「AqeusTalkTTS」


AquesTalk-ESP32は、辞書データのアクセスやD/A出力部分は、動作環境(ハードウェア)に応じて実装する必要があります。
そこで、AquesTalk-ESP32のインターフェースをラップしたプログラムAqeusTalkTTSを作りました。これで、アプリケーションから簡単にAquesTalk-ESP32を使うことができます。

また、AqeusTalkTTSは、表示やその他の処理と並行して動作できるように、非同期(バックグラウンド)で音声出力します。

このAqeusTalkTTSとAquesTalk-ESP32の関係を下図に示します。

 

図. AqeusTalkTTSとAquesTalk-ESP32の関係

 

アプリ側からは、AquesTalk-ESP32が隠ぺいされ、AqeusTalkTTSの関数だけを使います。


関数aqdic_XXX()は、辞書データをアクセスする関数群で、言語処理エンジンAqKanji2Romanから呼ばれます。今回は、辞書データをSDメモリカードのファイルとして書き込んで使用します。SDのアクセスには、SD.hを用いているのので、ArduinoIDEに依存しています。ESP32-IDF環境で使う場合は書き換えが必要です。他にも、辞書データをSPIシリアルフラッシュメモリに保存したり、初期化時にRAMに読み込んで使用するなどの方法もあるでしょう。その場合も、このaqdic_XXX()をハードウェア環境に応じて実装します。

 

関数DAC_XXX()は、D/A出力部分で、ここでは、I2Sを経由して内蔵の8bitDACから音声出力しています。外部I2S-DACを使ったり、PDM出力をする場合などは、ここを書き換えます。

 

AqResampleは、リサンプリングのライブラリです。AquesTalk picoの出力は8KHzのサンプリング周波数です。これを、折り返し雑音の影響を削減するため、24KHzにアップサンプリングしています。

 

このAqeusTalkTTSのソースとヘッダファイルは、次のSampelTTS.zipに含まれています。改変・配布は自由です。

 


■サンプルプログラム


 

ダウンロード:SampleTTS.zip

 

サンプルスケッチ SampleTTS は、AquesTalk-ESP32、AquesTalkTTSを使ったHelloWorldのようなものです。ArduinoIDE用です。以下の機能が有ります。


シリアル経由で漢字仮名交じりのテキストを受信し、それを音声合成出力します。
ArduinoIDEのシリアルモニタは日本語テキストを送信できないので、Tera TermなどUTF8が送信できる通信アプリを使用してください。

 

左ボタンの押下で、固定メッセージをplayK()関数で再生します。
ここで、発声中に、playK()やplay()関数を呼び出すと、発声中のメッセージは中断され、新たなメッセージが発声されます。

 

中ボタンの押下で、日付を1日から31日まで順に読み上げます。
ここでは、play()関数で音声記号列からの音声出力しています。
また、isPlay()関数で発声の終了を調べ、発声の終了後に、次の日付を読み上げています。

 

右ボタンの押下は、stop()関数で発声を止めます。

 

なお、事前に、上記「ビルド準備」に従って、AquesTalk-ESP32をインストールしておきます。
また、SDメモリカードへ辞書データを書き込んでおく必要もあります。AquesTalk-ESP32のパッケージに辞書データaqdic_m.binがありますので、aq_dicフォルダを作成して、その下にaqdic_m.binを書き込みます。辞書のサイズは約9MBです。書き込む方法は何でも良く、SDカードの刺さるPC等でコピーするのが手っ取り早いでしょう。辞書をコピーしたら、そのSDメモリカードをM5Stackに刺しておくことを忘れずに。

 


■AqeusTalkTTSクラスのメンバ関数


漢字のテキストからの音声合成と、音声記号列からだけの音声合成の場合で、使用する初期化関数が異なります。前者はcreateK()を、後者はcreate()を用います。


ちなみに、AquesTalk-ESP32はヒープメモリを一切使用せず、処理で使用するメモリ(ワークバッファ)をアプリ側で確保して、初期化時にその領域を指定する方法を用いています。AqeusTalkTTSは、初期化時にワークバッファをヒープ上に確保し、AquesTalk-ESP32に指定しています。ヒープの使用量は、createK()では21KB、create()では400Bです。
コードサイズも、createK()とcreate()では大きく異なり、create()だと170KBほど削減できます。AquesTalk-ESP32の言語処理エンジンAqKanji2Romanは、高速化のために、辞書データの一部をROM領域に持たせているためです。

 

int createK(const char *licencekey);
AqeusTalkTTSを初期化します。
最初に一度だけ呼び出します。
漢字を含む日本語テキストからの音声合成の場合、こちらを使用します。
引数には、AquesTalk-ESP32のライセンスキーを指定します。
これにより、ナ行、マ行がすべてヌと発声される制限が無くなります。

 

int create(const char *licencekey);
AqeusTalkTTSを初期化します。
音声記号列からの音声合成だけの場合、こちらを使用します。


void release();
AqeusTalkTTSの使用を終了するときに呼び出します。
初期化時にヒープに確保した、ワークバッファを解放します。

 

int playK(const char *kanji, int speed);
指定のテキストメッセージを音声出力します。
非同期関数で、発声はバックグラウンドで行われ、関数はすぐに戻ります。
引数kanjiには、漢字仮名混じりの文字列(UTF8)を指定します。
引数speedは話速で、50-300の範囲で指定します。デフォルトは100です。

 

int play(const char *koe, int speed);
playK()の漢字仮名交じりのテキストの代わりに、ローマ字音声記号列を指定します。

 

void stop();
発声を中止します。

 

bool isPlay();
発声中の場合はtrueを返します。

 

int getLevel();
発声中の波形の大きさを返します。リップシンクで用います。

 


■ライセンスキーの入手


AquesTalk-ESP32の評価版はナ行とマ行がすべてヌと発声される制限があります。ライセンスキーを購入することでこの制限が解除されます。

ライセンスキーの入手は、アクエストOnline Storeで「AquesTalk ESP32 使用ライセンス」を購入します。このとき備考欄に使用するESP32モジュールのMACアドレスを記載する必要があります。その後に郵送されるライセンス証にライセンスキーが記載されており、このライセンスキーをcreate()/createK()の引数に指定します。


・アクエストOnline Store「AquesTalk ESP32 使用ライセンス
 

 

■今後の予定


AquesTalk-ESP32に付属の辞書データですが、まだチューニングしていません。おかしな読み方も多々あるかと思います。
今後、辞書の整備を行って、品質を向上させる予定です。

 

 

■リンク


過去記事


ESP32で音声合成(AquesTalk pico for ESP32)


AquesTalk-ESPを簡単に使うクラス(プログラム)


省RAM版の言語処理エンジンのプロトタイプ開発
 

| AquesTalk | 19:26 | - | - |
PROFILE
Follow
CATEGORIES
LATEST ENTRIES
SEARCH THIS SITE
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND
SONY MDR-CD900ST
SONY MDR-CD900ST (JUGEMレビュー »)

普段これで開発しています。
RECOMMEND
RECOMMEND
RECOMMEND
RECOMMEND