classを一つにまとめてみる。

SAPI4, SAPI5, AquesTalkのどれかしか入っていない環境でも動作する様に一つにまとめてみる。

下記を tts.rb という名前で ruby libpath に置いて、ruby -rtts 'Tts.speak "お帰りなさいませ、御主人様"' とかすると、(何らかの音声合成エンジンが入ってたら)ちゃんと喋ってくれる筈。

#!/usr/bin/ruby -Ks
# -*- coding: shift_jis -*-
# 音声合成の為のクラス。
#AquesTalk API を使用したい場合は require 'tts' する前に↓この行を記述する。
#class Tts;@@method = 'AquesTalk';end
class Tts
  @@method = 'TextToSpeech.TextToSpeech' if !defined?(@@method)
  if @@method == 'AquesTalk'
    require 'Win32API'
    require 'kakasi'
    begin
      @@tts = Win32API.new('AquesTalkDa', 'AquesTalkDa_PlaySync', 'PL', 'L')
      def Tts.speak(str)
        yomi = Kakasi.kakasi('-JH -KH', str)
        @@tts.call(yomi, 120)
      end
    rescue
      @@method = 'TextToSpeech.TextToSpeech'
    end
  end
  if @@method == 'TextToSpeech.TextToSpeech'
    require 'win32ole'
    begin
      @@tts = WIN32OLE.new(@@method)
      def Tts.speak(str)
        @@tts.Speak(str)
        while @@tts.IsSpeaking != 0 do;end
      end
      def Tts.select(cond)
        n = (1..@@tts.CountEngines).find{|i|cond===@@tts.Speaker(i)}
        @@tts.Select(mode_name) if n
      end
    rescue
      @@method = 'SAPI.SpVoice'
    end
  end
  if @@method == 'SAPI.SpVoice'
    require 'win32ole'
    @@tts = WIN32OLE.new(@@method)
    def Tts.speak(str)
      @@tts.Speak(str)
    end
    def Tts.select(cond)
      v = @@tts.GetVoices
      n = (0...v.count).find{|i|cond===v.Item(i).GetDescription}
      @@tts.voice = v.Item(n) if n
    end
  end

  def initialize(cond=nil)
    Tts.select(cond) if cond
  end

  def speak(s)
    Tts.speak(s)
  end
end

if $0 == __FILE__
  t = Tts.new
  t.speak("おにーちゃん、大好き。")
end

どーでも良いことだが、/Naoko/さんで Tts.speak("Hello, World")とかすると、ちゃんと日本人風に「はろー、わーるど」と発声してくれるな。Microsoft Samに"こんにちは、世界"を渡しても無視してだんまりなのにねー。

/Naoko/さん、英語も喋れるんだな。バイリンギャル? (←死語)