macOS(Big Sur)のRuby(v2.6)でAquesTalk2

AquesTalk2のdyldをfiddle/importで読み込めなかったのでffiを使っています。
saronpasu/test_aques_talk2.rbを参考に書きました。

require "ffi"
module LibAquesTalk2
  extend FFI::Library
  ffi_lib "libAquesTalk2Eva.dylib"
  attach_function("AquesTalk2_Synthe_Utf8", "AquesTalk2_Synthe_Utf8", [:string, :int, :buffer_out, :int], :pointer)
  attach_function("AquesTalk2_FreeWave", "AquesTalk2_FreeWave", [:pointer], :void)
#  attach_function("my_printf", "printf", [ :string, :string ], :int)
end

class AquesTalk2_Error < StandardError; end
class AquesTalk2
  include LibAquesTalk2

  # 読み上げ速度の初期値
  DEFAULT_ISPEED =         100
  # 音声話者の初期値
  DEFAULT_PHONT  =           0
  # 出力ファイル名の初期値
  DEFAULT_OUTPUT = 'output.wav'
  
  # 読み上げ速度アクセサ
  attr_accessor :ispeed
  # 読み上げ話者アクセサ
  attr_accessor :phont
  # 出力ファイル名アクセサ
  attr_accessor :output

  # 引数なしでインスタンス生成された場合、初期値を用いる
  def initialize(ispeed = nil, phont = nil)
    @ispeed ||= DEFAULT_ISPEED
    @phont  ||= DEFAULT_PHONT
  end
  
  # テキストを音声へ変換する処理( AquesTalkライブラリのラッパーメソッド )
  def synthe(input, output = nil, ispeed = nil, phont = nil)
    begin
      raise(AquesTalk2_Error.new('input arg required.')) unless input
    rescue AquesTalk2_Error => error
      return false
    end
    
    input.chomp!
    output ||= DEFAULT_OUTPUT
    ispeed ||= @ispeed
    phont  ||= @phont

    begin
=begin
      result = @@synthe.call(input, ispeed, size = 0, phont) # ←このコードが実行された時点でコアダンプ
=end

=begin
      以下のように修正し、正常に動作しました。
=end
      size = [0].pack('i!')
      result = LibAquesTalk2.AquesTalk2_Synthe_Utf8(input, ispeed, size, phont)
      size = size.unpack('i!')
      size = size[0]

      p "size:" + size.to_s

=begin
      raise(AquesTalk2_Error.new('AquesTalk2_Synthe_Utf8 error: '+size.to_s)) if size.zero?
=end

=begin
      以下のように修正し、正常に動作しました。
=end
    if size == 0
      raise(AquesTalk2_Error.new('AquesTalk2_Synthe_Utf8 error: '+size.to_s))
      end
      rescue AquesTalk2_Error => error
      return false
    end

=begin
    open(output, 'w+b'){|f|f.print(result)}
=end
    
=begin
      以下のように修正し、正常に動作しました。
=end
    open(output, 'w+b'){|f|f.print(result.read_string(size))}


    free_wave(result)
    return true
  end
  
  # メモリ解放を行う処理のラッパーメソッド
  def free_wave(wav)
    LibAquesTalk2.AquesTalk2_FreeWave(wav)
  end
end

=begin
ここから、テスト処理です。
=end

# 評価用のテキストソース
sample_source = 'こんにちは、しずきたかひろです。'
# 出力ファイル名
sample_file = 'sample.wav'

# インスタンス生成
aques_talk = AquesTalk2.new
# テキストから音声ファイルを生成(AquesTalk2 ライブラリを実行)
aques_talk.synthe(sample_source, sample_file)

References

コメントをどうぞ

メールアドレスが公開されることはありません。 が付いている欄は必須項目です