BCCのお勉強したら、Windowsも喋ったよ。(2)

8年間、連続出場してた、「笑っていいとも」のタモリさんが、今週から計画停止で休みを 取っている。鉄人かと思っていたら、普通の人だった訳で、お疲れ様。ゆっくり休んで、悪い 所を十分に修理してくださいと応援したくなる。

タモリさんも凄いと思うけど、普通の人だって十分すぎる程凄いぞ。人によっては、100年も ずっと、無故障、無停止で動いているポンプを持っているんだもの。しかも、そのポンプ、 一回のどきっで、40ccだかの血液を送り出す。脈拍が60/分 だとすると、2.4リットル/分 の送出能力だ。一日にどのくらいになるか、計算してみるといい。

しかも、自動制御されてて、外界の状況(びっくりしたとか)とか、自分の状況(運動してる、寝てるなど) に合わせて、緩急自在に能力が変わる。緩急はともかく、100年間、無停止のポンプなんて 今の工学で可能なんだろうか?

迷惑な飛行物体である「蚊」。あの小さな体のくせに、りっぱなセンサー(二酸化炭素)を 持っていて、的確に食物を探知する。素早い手の動きに対して、さっと、身をかわす。 こういうのって、今の工学で作れるか? 私の知る限りでは、nil だな。

タモリさんのお休みに合わせて、ふと、こんな事を思った次第。合わせて読みたい「象の時間、 ねずみの時間」という本は、もう、処分してしまった。また、蚊ってくるかな。

新鮮な体験

昨日は気分を変えて、隣町にあるショッピングモールまで遠征。丁度、昼だったので、何か 食べよう。そうだ、寿司にしようとなりました。回転寿司です。注文は、写真をタッチでOK。 ベルトコンベアーから、支線へちゃんと、お皿が運ばれてきて、びっくりしたよ。

タッチパネルと指令塔とはどう結ばれているか、思わず裏側を覗いてしまったぞ。LANケーブル でしたね。今度、あの寿司屋へは、wiresheak持参で行きたいぞ。

も一つ、新鮮体験で、併設されてたスーパーでの出来事。セルフ精算機でレジ打ちを 体験しました。

バーコードが付いてない商品は、写真を出してから、それをタッチ。続いて個数をタッチ。 これで、「アスパラ___きゅーじゅーはち_えん___です」なんて具合に声で応答が返ったきた。 これには、AquesTalk - テキスト音声合成ミドルウェア が、組み込まれているのだろうか?

ちょうど今、hatuneなんていう喋るソフト(Windows native版)を作っているので、興味深かったよ。 さて、もうちょっと、hatuneを教育して、利口にしてあげよう。なにせ、生まれたばかり の女の子ですから。

hatuneの構成

hatune を、分解してみます。 まずは、hatune.bat

@echo off
ruby control.rb %1

前回書いた、hatune.rb は、ちょいと改名しました。無理してMVCを考えたら、controllerに なりますから。(って、matzさんの背広本の影響だったり、するのかな?)

control.rb とか、そこから呼ばれる、jsay.exe 等は、一式をPATHの通った所に入れて おきます。(たとえば、kakasi/bin の中とか -- 要control.rbのフルパス指定 -- 今は、hatuneの教育中なので、 保育園に入れてますが)その保育園の具合は

c:\sakae\test-kakasi>ls -l
-rw-   110592 2006-10-12 12:05 AquesTalkDa.dll
-rwx     1943 2009-07-15 10:58 control.rb*
-rwx       33 2009-07-14 16:19 hatune.bat*
-rwx    52224 2009-07-13 15:03 jsay.exe*
-rw-       85 2009-07-15 11:47 test.txt

test.txt は、hatuneのテスト問題です。

hatune の脳

hatuneの心臓は、jsayになるのかな? MVC で言ったら、V か。Vって、本来は、Viewの意味 だけど、Voice で、この場合はうまく語呂が合う。こちらは、前回のままです。

hatuneは、あれから、少し教育をして、(和製の)アルファベットと数字と、少々の記号を 喋れるようになりました。

親の影響を受けて、'(' を、かっこ、')' を、こっか と喋るようになったのは、ご愛嬌と 言う事で許してください。そんじゃ、脳みそ公開。

# Speak out text-file,  text-file must be sjis
# Usage: ruby control.rb text-file (called by hatune.bat)

infile = ARGV.shift
KAKASI = 'kakasi -JH -kH -s -u -osjis'

AH = { 'A' => 'えー', 'B' => 'びー', 'C' => 'しー', 'D' => 'でぃー',
       'E' => 'いー',  'F' => 'えふ',  'G' => 'じー', 'H' => 'えっち', 
       'I' => 'あい',  'J' => 'じぇい',  'K' => 'けー',  'L' => 'える',
       'M' => 'えむ',  'N' => 'えぬ', 'O' => 'おー',  'P' => 'ぴー',
       'Q' => 'きゅー',  'R' => 'あーる',  'S' => 'えす', 'T' => 'てぃー',
       'U' => 'ゆー',  'V' => 'ぶい',  'W' => 'だぶりゅー',  'X' => 'えっくす',
       'Y' => 'わい',  'Z' => 'ぜっと',
       '0' => 'ぜろ', '1' => 'いち', '2' => 'にー', '3' => 'さん', 
       '4' => 'よん', '5' => 'ご',  '6' => 'ろく',  '7' => 'なな',
       '8' => 'はち', '9' => 'きゅう',   }

KH = { '(' => 'かっこ', ')' => 'こっか', '-' => 'はいふん', '.' => 'どっと',
       '/' => 'すらしゅ',  ':' => 'ころん',  '@' => 'あっと', '+' => 'ぷらす', }

def adj(co)
  co = co.gsub(/\t/s, '')                                # Delete No allow char
  co = co.gsub(/[\(\)\-\.\/\:¥@\+]/s){|k| KH[k] + ',' } # Kigo
  co = co.gsub(/[a-z]/s){|s| s.upcase}                   # lower to upcase
  co = co.gsub(/[0-9A-Z]/s){|s| AH[s] + ',' }            # Num or Alpha to hatuon
  co.gsub(/ /, ',')                                      # make short priod
end

def say(s)
  fp = IO.popen( KAKASI, 'a+' )
    fp.print s
    co = fp.readline
    hi = adj(co)                       # Adj for AquerTalk
    printf(">>%s==%s~~%s\n", s, co, hi)  # Debug print
    system("jsay #{hi}")
  fp.close
end

def main(infile)
  puts 'このプログラムは、AquesTalk - テキスト音声合成を利用しています。'
  File.foreach(infile) do |al|
    al += "\r\n" unless al =~ /\n/  # adj line end (at last line of file)
    next if al =~ /^[ \t ]*$/s     # skip (hankaku|zenkaku) Space or TAB only line
    say(al)
  end
end

main(infile)

見ての通り、記号類は充実してません。知らない記号に出会うと、貝になってしまいます。 また、周りの空気を読んで、'-' を、マイナス なんて読む芸当も出来ません。後、ここには 現れていませんが、原稿に 'ぇ' なんて不純物が含まれていると、即、心臓停止か、悪く すると、マイクロソフトに密告しちゃう と言う、暴挙に出てしまいます。

使う場合は、全て自己責任でお願いします。私は、hatuneの生みの親ですが、子供が暴れて 損害が発生しても、その責任を取る事を放棄します。(大事な事ですから、もう一度言いますよ。 子供の責任は取りませんからね!)

なお、まだまだ、頭の悪い子ですから、いくら調教、もとえ、教育して頂いてもかまいません。 良い教育を施して自慢の子に育ったら、里帰りさせてください。親として、待ち望んでおります。

おっと、この地方の方言を教えるの忘れていました。'?' の発音は、"はてな", '!' は、"びっくり"って 言うんですからね。これを覚えておかないとダメよ、hatuneちゃん。

これだけ覚えさせれば、取り合えず、習わぬScheme教を読めるな。しめしめ。(これって、親のエゴ ですか。)

成果発表

それじゃ、型苦しい事は、置いておいて、ちょっと披露しますね。

c:\sakae\test-kakasi>hatune test.txt
このプログラムは、AquesTalk - テキスト音声合成を利用しています。
>>今、午前11時46分28秒です。
==いま 、 ごぜん 11 とき 46 ふん 28 びょう です 。
~~いま,、,ごぜん,いち,いち,,とき,よん,ろく,,ふん,にー,はち,,びょう,です,。

>>2009年7月15日、水曜日です。
==2009 ねん 7 がつ 15 にち 、 すいようび です 。
~~にー,ぜろ,ぜろ,きゅう,,ねん,なな,,がつ,いち,ご,,にち,、,すいようび,です,。

>>もうすぐ、お昼になりますよ。
==もうすぐ 、 お ひる になりますよ 。
~~もうすぐ,、,お,ひる,になりますよ,。

脳にセンサーを埋め込んで、何を思っているかモニターしてます。(って、ブレインのあの人 みたい)

>>の行は、入力された原稿
==の行は、kakasiをつかって、ひらがなに変換した結果
~~の行は、jsayに与える、発音データ

となっています。変なひらがなになってしまうのは、取り合えず、kakasiの辞書充実をすれば 良いと思います。(kakasiから、データを取り出しているから、MVC になぞらえるとMになるか。 そう考えると、control.rb内にある AH,KHのテーブルもMですな。-- Mって言うと、あれ みたいで、想像しちゃうでしょうから、言葉使いは難しいなー。)

喋らなくなったりする場合は、AquesTalkの資料を見て、control.rb に、手 を入れてください。

TODO

control.rb では、数字の棒読みしか出来ません。充実した数字の発声をサポートして 下さった(更には、そのDLLを公開くださった) AquesTalk開発者の皆様に感謝すると共に、申し訳ない気持ちで一杯です。

ちゃんと数字を読み上げるには、control.rb 内で、数字の列を取り出し、それをTAGでくくって、 jsayに渡してあげる必要があります。それには、例えば

co.sub( /(-?d+)(.?d+)?/s, '<NUM VAL=\1\2>' )

等として、数字をTAG内に埋め込みます。 (この正規表現は、即興ですから、信用しないように!)

問題は、<NUM VAL=123> のような(<> と半角スペースを含む)ものが、今のjsayでは、 受理できないのです。(コマンド引数渡しのため)

こういうデータをjsayにきちんと届けるには、PIPEを使うか、ファイル 渡ししか、解決方法がありません。(おっと、姑息に、環境変数って、手もあるか) いずれにしろ、jsayのソースを変更するはめになります。

LLで育った私は、カジュアルな事が好きですので、仕事でも無い限り、そこまで踏み込んで 改造に走る事は無いでしょう。

腕に自信のある、心臓外科医な方がおられましたら是非。。

夏の祭典

さあ、そろそろ夏の祭典 RubyKaigi2009の準備をして おかねば。頑張って "LET OVER LAMBDA" をGetするぞ。あれ? 何か違うよ。 Rubyはmatzさんの信念で未来永劫マクロが無い、matzLisp。

本物のLisperは、CLなり Schemeを使えと。(Schemeも一部のLisperからは、、以下自粛) LoLは、その為の指南書と言う訳か。会場で買ったら、あの方のサインを頂けるのだろうか? このことが、petite気になっております。