今 何時?

女房がアマゾンで時計を検索してた。実家の父の目が衰え、母に「今何時?」と、しょっちゅう 聞くものだから、時刻を声で教えてくれるのを探して、プレゼントしてあげようと思ったとの事。

で、見つけたのが、セイコーの電波時計 DA203S というやつ。別に電波時計でなくてもいいんだ けど、音声となると、これぐらいしか適当なものが無い。おいらが、アマゾンは嫌いじゃーと 言うと、だったら、東京へ行った時に買ってきてと下命されてしまった。

一応下調べしたら、アキバ価格で5140円だったよ。でも、ふらっと、昼の買出しに出た時に ホームセンターに立ち寄ったら、4980円で売ってた。アキバが安いとは限らないのね。

しゃべる時計

一応電波時計と言うので、nict.jpのお世話になります。毎00分に校正が行われ、ntpdで 同期を取っているパソコンと同じ時刻を表示しましたよ。

ボタンを押すと、「10時20分33秒です」なんて言う。ボタンを2回クリックすると「7月7日火曜日です」 なんて具合に教えてくれる。歳老いた父に、2回クリックが出来るかどうかは、ちょっと疑問 だけど、まあ、当初の目的は達成されました。

パソコンは喋るか?

5000円の時計が喋るなら、それよりも10倍は高価なパソコンがおしゃべりするのだろうか? と、ふと疑問が出てきた。

この時、頭をかすめたのは、ビューティフルコードに emacspeak というソフトを開発した方 が載っていたよなぁ。紐解いてみました。emacs自身が発声してくれると誤解してたけど、 そうじゃ無かった。Tcl で書かれた発声エンジンとemacsが通信して、目の不自由な方が emacsを操れるようにしたものなのね。

ネットで、このTclで書かれたと言うエンジンを探してみたけど探しきれなかった。残念! でも、面白いのを見つけたよ。

Windowsには、発声エンジンと音声認識機能が搭載されているんですって。 それをrubyからCOMに乗せてコントロールしている方がおられた。 またもや、灯台元暗し だったなあ。

Let speak english

日本語版のWindowsXPのくせして、日本語を喋る人は入っていなかった。せめて、言語明瞭、意味 不明瞭、難しい漢字はルビが振ってないと読めないぐらいの能力がある taroちゃんぐらいは 入れておいて欲しかったぞ。 >M$

入って無いものはしょうがないので、元サンプルを少々整理して、時計にしてみました。

require 'win32ole'

ap = WIN32OLE.new('SAPI.SpVoice')
se = ap.GetVoices                  # Get speak engine

en = nil
(0 .. se.Count-1).each do |i|
	id = se.Item(i).Id
	if (id.match(/MSSam/))         # find english speaker
		en = se.Item(i)
	end
end

ap.Voice = en                      # Select voice
ap.Rate = 1                        # Slow speed
ap.Speak(Time.now.to_s ,2)         # 2:sync mode

実行すると、ちゃんと喋ってくれたよ。数字は棒読みだけどね。

もう少し流暢にならないかな?

昔、某国へ出張した時の事。pinkのlampが灯るパブに入りましたよ。横に付いたおねーさんが 何か飲んでいい? なんて、おねだりされました。この場合の何かって言うと、それ用の シャンパンと相場が決まっています。

で、いいよ、でも、一応値段を確認。彼女の言う事にゃ、フィフティーン。 店を出る時、フィフティーを請求されましたよ。それ以来、値段は、Write it down pls. って 言って、騙されないようになりました。

無駄話になっちゃったけど、今回は、数字を与えると、話言葉に翻訳して喋って欲しい訳だ。 すぐに思いつくのは、rubyにテーブルを用意する事。でも、そんなのつまんないな。 Common Lispに、面白い機能があったな。

[1]> (format t "~R" 1234567890)
one billion, two hundred and thirty-four million, five hundred and sixty-seven thousand, eight hundred and ninety
NIL

後は、これを使って、時刻を英語に直せばいいわけだ。

;; what time is it ?

(defun main ()
  (multiple-value-bind 
    (second minute hour
     date   month  year
     day-of-weak daylight-p time-zone)
    (get-decoded-time)
  (format t "It's ~R ~R" hour minute)))

(main)	 
c:\sakae>time
現在の時刻: 14:01:08.38
新しい時刻を入力してください:
c:\sakae>clisp time.lisp
It's fourteen one

後は、上記rubyスクリプト中の Time.now.to_s を、 `clisp time.lisp` に変更 すればOK。それにしても、Windows上のrubyで、バッククォート構文が使えるなんて 開発の方、いい仕事してますねぇ。