喋るgauche
今、matzさんが書いた 背広本を読んでいる。背広本って、仲間内の隠語だけれど、分かるよね。 「まつもとゆきひろ コードの世界」が正式タイトルだ。
こういう呼び方は、ラクダ本に端を発していると記憶している。にしき蛇も居たなあ。つるはし 本もあったなあ。英語で言う方が通りが良いか。ピッケル本だな。
悪魔本なんてのもあるなあ。通りが悪かったら SICP、「計算機プログラムの構造と解釈」こちらは、 新(和田先生訳の2版)旧(上下2冊セット)合わせて持っている。
更に有名なのが、ドラゴンブック。こちらは、最初からチャレンジ出来ないと分かっていたので、 さすがに買うのは控えてました。
Gaucheをやるなら、ふぐ本だな。こうして見ると、表紙と言語(分野)が、リンク出来そうで 出来ない感じがする。
よく、言語を○○に例えると、と言うのがあって、最近では、schemeを天使に例えた人がいた。 近寄りがたいと感じられたようだけど、私はschemeが一番身近に感じるなあ。
しつこく音声合成をば
まずは、合成と対になる音声認識でお笑いをば 商業版なら、もう少しましなものと思っていたけど、、、理解出来るのは、wait,sit,run だけ だったら、お犬様だなあ。がんばって、10月27日(だったかな)を目指してください。
あれから、しつこく音声合成を探していたら、音声合成で Hellow, world にいきついた。
我らがエース小黒さんもc-wrapperを引っさげて、参戦されている。 面白そうなので、入れてみようかな。まてまて、それより先に、FreeBSDにも喋って貰わねば。 Windowsしか動きませんなんてのでは、非常に不愉快だからだ。
それにしても、皆さん、sayで 喋らせるんですね。perl6は、デフォがsayだったように記憶してるんで、いいのかな? ラリーおじさんは、print より say の方が、タイプするのが簡単とか言って、sayを採用したと 記憶してます。(違ってたら、スマソ)
BSDで使える音声合成エンジン
一つは、唇が悩ましいeSpeak もう一つは、歴史があり そうな Festival。どちらも、ports/audioに 入っていました。
Festivalの方は、英語、イタリア語、メキシコ語をサポートしてるようです。eSpeakは英語 のみですね。ちょいと実行するだけなので、簡単(と思われる)eSpeakを入れてみました。
eSpeak
manは無かったので、あたりを付けて
[sakae@fb ~]$ espeak -h eSpeak text-to-speech: 1.40 22.Dec.08 speak [options] ["<words>"] .... -k <integer> Indicate capital letters with: 1=sound, 2=the word "capitals", higher values = a pitch increase (try -k20). [sakae@fb ~]$ espeak -h | espeak --stdin
最後の行は、自身の説明書を自分自身に喋らせる例です。こういうのも、再帰と言うので しょうか? 説明書によると、ファイルを指定して読み上げさせたり、読み上げさせる変わりに、waveファイルに 落としたりできるようです。実際にやってみると、
[sakae@fb ~]$ ls -l say.man -rw-r--r-- 1 sakae kuma 572 Jul 8 12:02 say.man [sakae@fb ~]$ file say.man say.man: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 22050 Hz
必要十分ですね。
喋るgauche
さて、材料は揃いました。小黒さんの c-wrapper版
(use objc-wrapper) (c-load "Cocoa/Cocoa.h" :libs "-framework Foundation -framework Cocoa") [[NSAutoreleasePool :alloc] :init] (define say (let1 s [[NSSpeechSynthesizer :alloc] :init] (lambda (str) [s :startSpeakingString (@ str)]))) (say "Hello, world")
より、短く書けるかな? (あのー、golf じゃないんですから、無理しなくてもいいよ)
(define (say s) (sys-system #`"espeak ,s")) (say "hello world")
あれ、こんなに簡単だったかなあ?
schemeのソースを読み上げる時、"(" は、カッコと ")"は、コッカと読み上げて欲しいんだ けど、どうしたら良いだろう? gauche側で、espeakに渡す前に、変換しちゃうのがいいか、 espeak側で、"("を、カッコと発声させるのがいいか。悩むなあ。
気楽に構えていたら、こういうのはエラーに落ちるよ。
gosh> (say "Hellow world") 0 gosh> (say "hello (sakae)san") Syntax error: "(" unexpected 512
何処に落とし穴が潜んでいるやら?
Say Yes じゃなくて、say me
そんじゃ、こんなのはどうだろう?
(define (say s . opt) (let-optionals* opt ((file-opt "")) (sys-system #`"espeak ,file-opt ,s")))
gosh> (say "spk.scm" "-f") 0
省略可能な第二引数に、"-f" を指定すると、第一引数をファイル名と解釈して、読み上げる やつだ。これなら、カッコを含んでいてもへっちゃらだい。って、超カッコ悪いぞ!!
でも、冷静に上記のエラーを見ると、512 って何よ? gauche が出しているエラーじゃ無い よね。shell側のエラーだよ、きっと!
[sakae@nil ~]$ espeak hellow world [sakae@nil ~]$ echo $? 0 [sakae@nil ~]$ espeak hellow (sakae)san -bash: syntax error near unexpected token `(' [sakae@nil ~]$ echo $? 258
ピンポン。ここまで分かれば
(define (say s . opt) (let-optionals* opt ((file-opt "")) (sys-system #`"espeak ,file-opt ',s'")))
これで大丈夫。微妙な穴だったよ。後は、みっともないオプションを直しておこう。
(define (say s . opt) (let-optionals* opt ((file "")) (when (keyword? file) (set! file "-f")) (sys-system #`"espeak ,file ',s'")))
gosh> (say "spk.scm" :file) 0