クリップボード文章も読み上げるぜい!

zaurusで長文の日本語音声を読み上げることが(やっと、、)できましたので公開です!。

ベースとなっているのはこちらのサイト
(実践編)Zaurusで日本語音声合成 MBROLA+muDaTTS: 旧式ひとりぶろぐ

これらをすべてSL-C1000に導入することからスタート!。
まずはspeakコマンドで正しく日本語が発音できることを確認して下ださい。
これで発音できなければ当方のプログラムを準備しても発声できません(汗)

  • talkコマンドの準備

上記ひとりブログ様の標準添付ウェア「speak」では引き渡された日本語を発音するまでに
10秒程度必要としています。
またたとえば
「こんにちわ。」
「僕ザウルスです。」
といった2行の文章を読ませるためには

#echo "こんにちわ。"|speak
#echo "僕ザウルスです。"|speak

といったように各人で2行に分けて実行する必要がありますし、
また「こんにちわ」と「僕ザウルスです。」の発生の間に再び音声ファイルを準備する為に
10秒程度時間が必要となります。
そこで、
talk」コマンドの紹介です。
以下のコードを
/home/QtPalmtop/bin

talk」という名前で保存し、実行権限を
chmod +x talk
とします。
また事前にnkfkakasiのインストールが必要です。
さらにはSDカードにtmpディレクトリを作成します。

#mkdir /mnt/card/tmp

talkスクリプトソース

#!/bin/bash


INPNAME=$1

TMP=/mnt/card/tmp
TMP2=/mnt/card/tmp

CT1=0
CT2=0

qcop_taskbar(){

        qcop QPE/TaskBar 'message(QString)' "$MESS"

}


make_raw(){

        CT1=0
        while read RLINE1
        do

                if [ "$RLINE1" ];then
                        MES="Make>> ${TMP}/speak.$$.$CT1.raw now";echo $MES
                        echo $RLINE1"__"|
                        /opt/QtPalmtop/bin/zmuDaTTS.rb |
                        mbrola /opt/QtPalmtop/lib/voices/jp2 - - >${TMP}/speak.$$.$CT1.raw
                else
                        touch ${TMP}/speak.$$.$CT1.raw
                fi
                        touch ${TMP}/speak.$$.$CT1.lock

                CT1=$(($CT1 + 1))

                while [ $(($CT1+5)) -lt $CT2 ]
                do
                        a=0
                done

        done < $INPNAME
}

speak_raw(){

        MESS="Speak Start";echo $MESS;qcop_taskbar
        sleep 1

        for i in message01 message02
        do
                MESS="Speak>>$i.raw";echo $MES
                cat ${TMP2}/$i.raw|sox -t raw -r 22050 -w -s -c 1 - -t ossdsp /dev/dsp
                MESS="1 line Speak end.";echo $MES
                sleep 3
        done

        sleep 1
        CT2=0

        while read RLINE2
        do

                until [ -f ${TMP}/speak.$$.$CT2.lock ]
                do
                                a=0
                done

                MESS="Speak>> ${TMP}/speak.$$.$CT2.raw";echo $MESS
                echo $RLINE2|tr "_" " "|nkf --utf8
                #echo $RLINE2|nkf --utf8
                cat ${TMP}/speak.$$.$CT2.raw|sox -t raw -r 22050 -w -s -c 1 - -t ossdsp /dev/dsp
                echo "Speak end."
                rm -f ${TMP}/speak.$$.$CT2.raw
                rm -f ${TMP}/speak.$$.$CT2.lock
                CT2=$(($CT2 + 1))

        done < $INPNAME

        for i in message03
        do
                MESS="Speak>>$i.raw";echo $MES
                cat ${TMP2}/$i.raw|sox -t raw -r 22050 -w -s -c 1 - -t ossdsp /dev/dsp
                MESS="1 line Speak end.";echo $MES
                sleep 2
        done

}

if [ -f $1 ]; then

        INPNAME=$TMP/copy.txt

        cat $1|nkf --euc|sed 's/ /\_/g' |
        sed 's/\./\_dot\_/g'|sed 's/,/\_comma\_/g'|
        kakasi -Ej|tr -d '\r' |tr -d '\n'|tr . '\n'|
        sed 's/,/\_\_/g'|sed 's/ /\_\_/g' |
        sed 's/\_dot\_/\./g'|sed 's/\_comma\_/,/g'>$INPNAME

        echo "">>$INPNAME



        make_raw  &
        speak_raw

        rm -f $INPNAME

else

        MES="$INPNAME not found.";echo $MES;qcop_taskbar &

fi

また本プログラムでは3つの音声ファイル「message0?.raw」ファイルを必要とします。
標準添付の「speak」プログラムを以下のように一部変更します。

#!/bin/sh

export TMP=/mnt/card/tmp

if [ -f $1 ]; then
        cat $1 |
        /opt/QtPalmtop/bin/zmuDaTTS.rb >${TMP}/zmudatts_temp$$.pho

        cat ${TMP}/zmudatts_temp$$.pho |
        mbrola /opt/QtPalmtop/lib/voices/jp2 - - >${TMP}/zmudatts_temp$$.raw

        cat ${TMP}/zmudatts_temp$$.raw |
        sox -t raw -r 22050 -w -s -c 1 - -t ossdsp /dev/dsp

        #rm ${TMP}/zmudatts_temp$$.raw ${TMP}/zmudatts_temp$$.pho
else
        echo "file ${1} not found."
fi

上記のように作成したrawファイルを削除しないようにさせて

「現在音声ファイルの準備中です。」←message01.raw
「しばらくお待ちください。」←message02.raw
「以上で、読み上げ終了です。」←message03.raw

となるようにたとえば、
message01.txt

現在音声ファイルの準備中です。

を用意してzaurusのターミナルから

#cat message01.txt|speak

として/mnt/card/tmpに作成されたrawファイルをmessage01.rawと変更して
そのまま/mnt/card/tmpにおきます。
同様にして合計3ファイルを/mnt/card/tmpに配置します。
これでtalkコマンドは利用できます。
使用方法はspeakコマンド同様、

#cat test.txt|talk
#talk test.txt

などとして利用します。
また内部でkakasiを利用することで引き渡されたテキスト文章を解析して
句読点で読み上げの区切りとするように整形しなおします。
これにより
サイショの例に合ったような
「こんにちわ。」
「僕ザウルスです。」
も「こんにちわ。僕ザウルスです。」とつなげたテキストファイルを受け渡しても
問題なく読み上げてくれます。

クリップボードからの引渡しをするために以下のプログラムを用意します。
本プログラムはこちらのサイトを参考にRubyで作成されています。
ZaurusTips - Miyo's Page

#!/usr/bin/env ruby
require 'qte'
include Qte
a = QApplication.new([$0]+ARGV)
cb = QApplication::clipboard
codec = QTextCodec.codecForName('eucJP')
print codec.fromUnicode(cb.text).to_str

これを
/mnt/card/shells/clipin.rb
として保存します。
利用方法は以下のようにします。
まずメモ帳などを開いて任意のテキストをコピーします(メニューやショートカットどちらでもよい)。
次にターミナルから以下のようにします。

cd /mnt/card/shells
./clipin.rb 2>&1|grep -v "SlSharedManager"|grep -v "Display size = 480x640"|talk

これでコピーされた文章が読み上げられればOKです。
ちなみに、、、
clipin.rbは自分の環境では/mnt/card/shellsにおいてありますが
talk同様/home/QtPalmtop/binでもかまいません。

  • keyhelper設定

いよいよkyehelperの設定です。
keyhelper.confを開き以下のように設定します。
[Lunch」セクションにて

V = @exec       /mnt/card/shells/clip2talk.sh

[Menu]セクションにて

03_クリップボード読み上げ(&V) = @exec   /mnt/card/shells/clip2talk.sh

とします。
keyhelper設定をリロードすれば準備完了・・・と思ったら上記
/mnt/card/shells/clip2talk.shを準備するのを忘れてましたね(汗)
clip2talk.sh

#!/bin/bash

qcop QPE/BatteryPlus 'change(QString)' "Hi Mode"

WORKDIR=/mnt/card/shells

cd $WORKDIR
./clipin.rb 2>&1|grep -v "SlSharedManager"|grep -v "Display size = 480x640"|talk

qcop QPE/BatteryPlus 'change(QString)' "Low Mode"

上記ではこちらの
http://piro.sytes.net/~piro/pukiwiki/pukiwiki.php?BatteryPlus
を利用し音声読み上げの際にCPUクロックアップなども行っています。
ここら辺は好みで変更してみてください。

これで動画のようにウィキペディアなど長文をコピーしてメニューや
ショートカットキーにて読み上げさせることができるようになります。

他にもQualender(SQLite3版)のデータベースにアクセスして
今日のスケジュールを読み上げるなんてプログラムも組んだのですが、、、
そのうち気が向いたらアップします。
要望などありましたらコメントまで!

ああ、また長文になってしまった(爆)