投稿者: nishimotz

  • NVDA + GalateaTalk

    昨日の日記の続きです。gtalk.pyは今日はこんな感じになってます。

    class SynthDriver(silence.SynthDriver):
    name = "gtalk"
    description = "galatea talk (experimental)"
    def initialize(self):
    os.chdir("c:\\work\\istc\\SSM\\gtalk")
    cmd = "gtalk -C ssm-win.conf"
    (self.cout, self.cin) = popen2.popen4( cmd )
    self.cin = codecs.getwriter('shift_jis')(self.cin)
    self.cin.write("prop Speak.text = NoAutoOutput\n")
    self.cin.write("prop Speak.pho = NoAutoOutput\n")
    self.cin.write("prop Speak.dur = NoAutoOutput\n")
    self.cin.write("prop Speak.stat = NoAutoOutput\n")
    self.cin.write("prop Speak.len = NoAutoOutput\n")
    self.cin.write("prop Speak.utt = NoAutoOutput\n")
    self.cin.write("set AutoPlay = YES\n")
    self.cin.flush()
    self.frame = SynthFrame()
    return True
    def speakText(self,text,wait=False,index=None):
    self.cin.write("set Text = " + text + "\n")
    self.cin.flush()
    if wait:
    s = "[speak wait]"
    else:
    s = "[speak]"
    self.frame.textCtrl.AppendText(s + text + "\n")
    def cancel(self):
    self.cin.write("set Speak = STOP\n")
    self.cin.flush()
    self.frame.textCtrl.AppendText("[cancel]\n")
    def terminate(self):
    self.cin.write("set Run = EXIT\n")
    self.cin.flush()
    if not self.frame:
    return
    self.frame.Close()
    self.frame.Destroy()
    self.frame = None
    def getVoiceName(self,num):
    return "gtalk voice"
    

    で、今度は5~6行くらいは読み上げるようになりました。カーソルで行を移動すると「音切れ」もちゃんと実現されています。ちょっと反応が遅く感じるのは GalateaTalk の処理時間の問題でしょう。

    数行読み上げるとやがて止まってしまうのは GalateaTalk のコンソール出力をちゃんと読み出ししていないから不安定なのかも知れません。

    そもそも cout の読み出しをどうやればいいのでしょう。別スレッドを回して non-blocking I/O でcoutを読み出して捨てる必要があるのですが、まだ Python に慣れていない私はそこでつまづいています。

    ところで GalateaTalk の README には

    各スロットは、プロパティとして AutoOutput か NoAutoOutput のどちらかの
    値をとり、それぞれ自動出力する、自動出力しないを表す。
    プロパティの値を変更するには、
    prop Text.text = NoAutoOutput
    prop Text.text = AutoOutput
    のように prop コマンドによって行なう。
    初期値としては、全て AutoOutput が設定されている。
    

    と書かれているのですが、サンプルのPerlスクリプト(RUN)は

    print OUT "prop Text.text = NoAutoOutput\n";
    print OUT "prop Text.pho = NoAutoOutput\n";
    print OUT "prop Text.dur = NoAutoOutput\n";
    

    になっています。これ Text.text ではなくて Speak.text じゃないでしょうか?

    今日はここまで。

  • Python + GalateaTalk

    NVDA というオープンソースのWindows用スクリーンリーダーで GalateaTalk が使えないか、という話があったので、調べてみました。

    最新の NVDA snapshots には NVDAJp の活動の成果が取り込まれています。

    まず、python で gtalk を実行してみます。下記を UTF-8 で保存して実行。

    # -*- coding: utf-8 -*-
    import popen2
    import os
    import codecs
    os.chdir("c:\\work\\istc\\SSM\\gtalk\\")
    cmd = "gtalk -C ssm-win.conf"
    (cout, cin) = popen2.popen4( cmd )
    cin = codecs.getwriter('shift_jis')(cin)
    text = u'こんにちは'
    cin.write("set Text = " + text + "\n")
    cin.write("set Speak = NOW\n")
    for line in cout.readlines():
    print line
    

    あちこちからパクったソースです。「こんにちは」と喋ってくれました。

    次は NVDA のドライバー実装です。

    NVDA/synthDrivers/display.py をコピーして gtalk.py を作り、

    class SynthDriver(silence.SynthDriver):
    name = "gtalk"
    description = "galatea talk (experimental)"
    

    にしてみたら、とりあえず NVDA 起動→ Ctrl-Shift-S で gtalk が選択可能に。

    def initialize(self):
    os.chdir("c:\\work\\istc\\SSM\\gtalk")
    cmd = "gtalk -C ssm-win.conf"
    (self.cout, self.cin) = popen2.popen4( cmd )
    self.cin = codecs.getwriter('shift_jis')(self.cin)
    text = u'子猫が隠れんぼをしています'
    self.cin.write("set Text = " + text + "\n")
    self.cin.write("set Speak = NOW\n")
    self.frame = SynthFrame()
    

    gtalk ドライバー選択時に「子猫が・・」と喋ってくれました。

    def speakText(self,text,wait=False,index=None):
    self.cin.write("set Text = " + text + "\n")
    self.cin.write("set Speak = NOW\n")
    self.frame.textCtrl.AppendText(text + "\n")
    

    お、最初の2行くらい喋った!!

    でも、すぐに音声合成がハングアップ。やっぱり「音切れ」の処理を実装しないとダメですね。

    続きは明日!!

  • Ruby on Rails ふたたび

    ひさしぶりに CodeGear 3rdRail を触っています。

    きっかけはインプレスジャパンのこの本です。

    基礎Ruby on Rails (IMPRESS KISO SERIES)

    基礎Ruby on Rails (IMPRESS KISO SERIES)

    Ruby on Rails の環境、ライブラリ群、そして Ruby 言語の、すべてにおいて初心者の人を対象にした本であり、とても読みやすいと思います。

    この本を片手に 3rdRail で遊ぶのも、なかなか良さそうです。

    この本の第1章だけを試してみて、こんなことを思いました。

    • RoR を単なるテンプレートエンジンとして使うところから出発して、だんだんまともなアプリケーションに向かってリファクタリングしていく、というのもアリじゃないか?

    そこで来月のWIT研究会のページを作成する作業をやってみました。

    いままで ActivePerl と Template-Toolkit を使ってやってきた作業を、index.rhtml と main_controller.rb の index メソッドだけで実装し直してみました。rhtml の中で ruby が直接使えるのが嬉しいです。そして index の中にはひたすらハッシュ配列の代入文が並んでいます。そんだけかい。。

    階層化アーキテクチャによるアプリケーションにおいては、けっきょく、各レイヤの要になるのはテンプレートエンジンではないか、と思います。マルチモーダル対話アーキテクチャの標準化委員会にこの数年関わっていますが、そこで議論していても常々思います。

    3rdRail では rb ファイルでしかメソッドの入力補完は効かないようですが。。あと、実行時エラーのときにやたら重くなるのはなぜだろう。。

    RoR はあっちこっちのレイヤで縦横無尽にテンプレートエンジンが使えるのが魅力です。yml の中で eRuby を使う例を最初に見たときは目から鱗が落ちました。

    そんなわけで、ちゃんとデータモデルを使えるように勉強を続けたいと思います。