Raspberry Pi 2を喋らせる
今回は音声合成を試してみた。
音を鳴らすには
デフォルトでは音声はHDMI出力になっているらしい。
普段Macからターミナルで操作しているので、そのままでは音が鳴らない。
音声の出力先をRaspberry Pi 2本体のオーディオ端子に変更した。
$ amixer cset numid=3 1
amixer cset numid=3 1の1がオーディオ端子で2がHDMI端子らしい。
オーディオ端子にスピーカーを接続し、音が出るか確認。
$ aplay /usr/share/sounds/alsa/Front_Center.wav
喋らせる準備
Raspberry piで音声合成するソフトは、AquesTalkとOpen-jtalkの2つが有力らしいが、個人的にゆっくりボイスが好きなので、それに近いAquesTalkの方を選んだ。
下記サイトからダウンロードする
AquesTalk Pi - Raspberry Pi用の音声合成
raspberry piから直接ダウンロードできなかったので、
macのブラウザで表示し、利用規約に同意してダウンロードした。
ダウンロードしたファイルをscpコマンドでraspberry piに転送。
$ scp [ダウンロードした場所]/aquestalkpi-20130827.tar.gz [アカウント名]@[raspberry piのIPアドレス]:~/
aquestalkpiを解凍
$ tar xzvf aquestalkpi-20130827.tar.gz $ cd aquestalkpi
とりあえず喋らせてみる
$ ./AquesTalkPi "ゆっくりしていってね!" | aplay
今回は、定型文を喋らせたかったので、ファイル化してプログラムから呼び出すことにした。
まずwavファイルとして出力する。
$ ./AquesTalkPi -b "ザッケンナコラー!" -o yakuza01.wav $ ./AquesTalkPi -b "スッゾコラー!" -o yakuza02.wav $ ./AquesTalkPi -b "チェラッコラー!" -o yakuza03.wav $ ./AquesTalkPi -b "テメッコラー!" -o yakuza04.wav $ ./AquesTalkPi -b "ドグサレッガー!" -o yakuza05.wav $ ./AquesTalkPi -b "イヤーーーッ!" -o IYA01.wav $ ./AquesTalkPi -b "グワーーーッ!" -o GUWA01.wav
c言語からwavファイルを鳴らすには、直接aplayコマンドを呼べばいいと思い、systemコマンドで呼ぶことにした。
systemコマンドに渡す文字列引数の末尾に"&"を付けておけば、シェルと同様に終了を待たずに実行されるのが面白い。
プログラム
#include <iostream> #include <iomanip> #include <vector> #include <cstdio> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/joystick.h> #include <stdlib.h> #define JOY_DEV "/dev/input/js0" using namespace std; int main() { int joy_fd(-1), num_of_axis(0), num_of_buttons(0); char name_of_joystick[80]; vector<char> joy_button, joy_button_old; vector<int> joy_axis; const char *talkdata[] = { "aplay -q yakuza01.wav &", "aplay -q yakuza03.wav &", "aplay -q yakuza04.wav &", "aplay -q yakuza05.wav &", "aplay -q yakuza06.wav &", "aplay -q IYA01.wav &", "aplay -q GUWA01.wav &", "date +\"現在%m月%d日%p%I時%M分%S秒ダッコラー!\" | ./AquesTalkPi -f - | aplay -q &", }; if((joy_fd = open(JOY_DEV, O_RDONLY)) < 0) { printf("Failed to open %s", JOY_DEV); cerr << "Failed to open " << JOY_DEV << endl; return -1; } ioctl(joy_fd, JSIOCGAXES, &num_of_axis); ioctl(joy_fd, JSIOCGBUTTONS, &num_of_buttons); ioctl(joy_fd, JSIOCGNAME(80), &name_of_joystick); joy_button.resize(num_of_buttons, 0); joy_axis.resize(num_of_axis, 0); joy_button_old.resize(num_of_buttons); printf("Joystick: %s axis: %d buttons: %d\n", name_of_joystick, num_of_axis, num_of_buttons); fcntl(joy_fd, F_SETFL, O_NONBLOCK); // using non-blocking mode while(true) { js_event js; read(joy_fd, &js, sizeof(js_event)); switch(js.type & ~JS_EVENT_INIT) { case JS_EVENT_AXIS: joy_axis[(int)js.number] = js.value; break; case JS_EVENT_BUTTON: joy_button_old[(int)js.number] = joy_button[(int)js.number]; joy_button[(int)js.number] = js.value; break; } for(int x=0 ; x<num_of_buttons ; ++x ) { if (( joy_button[x] == 1 )&&( joy_button_old[x] == 0 )) { if ( x < 9 ) { printf("button[%d] on speak %s\n", x, talkdata[x]); system(talkdata[x]); } } } usleep(100); } close(joy_fd); return 0; }
せっかく自由に喋らせられるので、申し訳程度に現在時刻も喋らせるようにした。
aplayコマンドは同時に複数の音声が再生できるが、あまり同時リクエスト数が多いとエラーがでる模様。
音量調整
100均のスピーカーを繋いで再生させてみたが、音が小さすぎて聞こえない!
音量調整はalsamixerというコマンドで行う。
$ alsamixer
カーソルキーの上下で音量調整ができる。
ESCで設定して終了。
初期値が40%だったので70%にしてみたがまだ小さかった。
思い切って100%にしたら少しマシになった。
100均で買ったスピーカーだからだろうか…。
動作確認
音が出ると
楽しい!
✌ ('ω' ✌ )三 ✌ ('ω') ✌ 三( ✌ 'ω') ✌