BCCのお勉強したら、Windowsも喋ったよ。うひょ。

昨日は、月に2回の、グルーミングデーだった。ここ数十年は床屋へ行っていない。女房が、バリカンで 高校球児宜しく、3分の丸坊主にしてくれる。

床屋へ行く面倒さも無いし、手入れが簡単なので至極気に入っている。最初は、丸坊主に女房が 難色を示し、グラディーションを付けたGI風カットと言うか、職人風だったんだけど、そのうちに、 女房が、折れて、数年前からは、丸坊主。

ピョンと数本特異的に延びた、眉毛を切って貰って、女房の担当分は終了。残りの、鼻毛、爪きり、 耳掃除は、セルフサービスだ。

鹿児島の女性を女房にすると、靴下を履かせてくれたと友人が言っていたけど、もしうちの 女房が鹿児島女子だったら、グルーミングをセットでやってくれるんだろうか?

猫でも分かるプログラミング

先日、Windows用のfree版喋るdll をちょっと試してみた。その時は、VC++でのサンプルが 付属してたので、諦めてたのだ。けれども、ちょっと出来心が出て。

うちのWindows機には、BCCが入っていたのだ。ひょっとして、これならdllだって使えちゃう んでないかいと、素人っぽく思った訳だ。確かそのBCCは、 猫でも分かるプログラミングBCCでプログラムを作ろうを参考に 練習した覚えがある。

で、カミングアウトしちゃうと、途中で挫折してしまい、それっきりになっていたのだ。こういう おいらは、猫以下って事になる。さあ、リベンジ成るか? 見ておかなければならないのは、第11章 dllを作る かな。

dll と連携させる

AquesTalkのサンプルから、AquesTalkDa.h AquesTalkDa.lib を引っ張ってきた。プロジェクト dir(今回は、sndとした)へ入れてあげる。また、Debug-buildするので、Debug-dirの中には AquesTalkDa.dllを入れておく。

こんな環境の中で、簡単なcppファイルを作った。(例題をコピーして、ちと変更)

c:\borland\work\snd>cat HelloTalk.cpp
#include <stdio.h>
#include <stdlib.h>
#include "AquesTalkDa.h"

main(){
    return AquesTalkDa_PlaySync("こんにちわ。");

}

こんにちわ。と喋って欲しいのだ。喋るんじゃなくて、ファイルに落とすには、サンプルの 例題そのままで、いいのかな。

猫でもに習って、プロジェクトメニューのプロジェクト設定から、リンクのタブを選び、 AquesTalkDa.lib を追加しておく。 これが、dllを使うための、おまじないらしい。

コンパイルしてみると

> C:\borland\bcc55\Bin\make.exe -fDebug\snd.mak -B TARGET
MAKE Version 5.2  Copyright (c) 1987, 2000 Borland
	bcc32 -WC -5 -Od -w -AT -pc -H- -k -b -v -y -DDEBUG -nDebug  -c C:\borland\work\snd\HelloTalk.cpp
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
c:\borland\work\snd\hellotalk.cpp:
	bcc32 -WC -5 -Od -w -AT -pc -H- -k -b -v -y -DDEBUG -eDebug\snd.exe Debug\HelloTalk.obj C:\borland\work\snd\AquesTalkDa.lib
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 'C:\BORLAND\WORK\SND\AQUESTALKDA.LIB' contains invalid OMF record, type 0x21 (possibly COFF)

** error 1 ** deleting Debug\snd.exe

Build End !! (Elapsed time 0:01.833)

見事に失敗してる。でも、良く見ると、サンプルから持ってきた、AQUESTALKDA.LIB が、BCCの リンカーのお気に召さなかったようだ。後ちょっとなので、先生に聞いてみた。

解決編

dllを元にして、BCCのリンカーに馴染むようにlibを作成するツールがあるそうな。

c:\borland\work\snd>ls -l *lib *dll
-rw-   110592 2006-10-12 12:05 AquesTalkDa.dll
-rw-     3230 2006-10-12 12:05 AquesTalkDa.lib

c:\borland\work\snd>implib AquesTalkDa.lib AquesTalkDa.dll

Borland Implib Version 3.0.22 Copyright (c) 1991, 2000 Inprise Corporation
c:\borland\work\snd>ls -l *lib *dll
-rw-   110592 2006-10-12 12:05 AquesTalkDa.dll
-rw-     1536 2009-07-12 20:15 AquesTalkDa.lib

こうしておいてから、再コンパイルしてみると

> C:\borland\bcc55\Bin\make.exe -fDebug\snd.mak -B TARGET
MAKE Version 5.2  Copyright (c) 1987, 2000 Borland
	bcc32 -WC -5 -Od -w -AT -pc -H- -k -b -v -y -DDEBUG -nDebug  -c C:\borland\work\snd\HelloTalk.cpp
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
c:\borland\work\snd\hellotalk.cpp:
	bcc32 -WC -5 -Od -w -AT -pc -H- -k -b -v -y -DDEBUG -eDebug\snd.exe Debug\HelloTalk.obj C:\borland\work\snd\AquesTalkDa.lib
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

Build End !! (Elapsed time 0:02.484)

コンパイルでけた。しゃべったよ。 参考までに、Makefileが、Debugの中にあったので、掲載

c:\borland\work\snd\Debug>cat snd.mak
#-------------------------------------------------------
# BCC Developer 1.2.21
# Copyright (C) 2003 jun_miura@.........jp
#-------------------------------------------------------
.autodepend
CC=bcc32
RC=brc32
CFLAG=-WC  -5 -Od -w -AT -pc -H- -k -b -v -y  -DDEBUG
OUTDIR=-nDebug
CINCS=
TARGET=Debug\snd.exe
SRC1=C:\borland\work\snd\HelloTalk.cpp
OBJ1=Debug\HelloTalk.obj
LIB1=C:\borland\work\snd\AquesTalkDa.lib

TARGET: $(TARGET)

$(TARGET): $(OBJ1)
    $(CC) $(CFLAG) -e$(TARGET) $(OBJ1) $(LIB1)

$(OBJ1): $(SRC1)
    $(CC) $(CFLAG) $(OUTDIR) $(CINCS) -c $(SRC1)

BCCなかなかやるじゃん。後は、このサンプルをいじっていけばいいんだな。 どういじる。その前に、も一つ難題が。そう、Windows用のkakasiがあるかだ。

探してみたよ。Windnows-kakasi この近辺をうろうろ してたら、kakasi を使ってるアプリケーションとして、 yomi が、しっかりリストアップ されてた。

Windows版喋るの設計

さあ、材料は揃った。全体をコントロールするのは、rubyにしておく。 rubyだとkakasiを便利に使うモジュールがあるようだ。喋るプログラムへの インターフェースはどうしよう?

パイプで渡しちゃうのが簡単そうだけど、Windowsの偽パイプは途中で 詰まったりしないかな。次の選択子は、引数渡しだけど、環境エリアの サイズと、0x5C問題は無いかが心配。ああ、ほとんどがひらがなだから 大丈夫?

一番無難なのは、ファイル渡しか。rubyだと temp-fileが使えるから 落ちても、ゴミファイルが残る事は少なそう。でも、1行毎にファイルを 作成して、使って(喋り終わったら)削除の繰り返しじゃ、HDDへの負担 大きそう。まてよ、Windowsは、遅延書き込みなんてサポートしてるかな?

これにて、検討終わり。後は、得意のカット&トライの出番です。

まてまて、喋るプログラムの制限で、発声通りに変換してあげないと てにをはを間違えた、外人みたいになっちゃうぞ。

「私は、小林です。」 --> "わたしわ、こばやしです。" に変換等。 先輩の yomi-lib.pl では、どうしてるのだろう。まてまて、そこまで思いを馳せる前に 幹の構築だな。

構築編

rubyから、kakasi を読んで、ひらがなを出すスクリプトを まず、unixで書いてみた。ちょっとWindowsでは動くかどうか分からない 危なっかしい事をやっちゃったけど、そのまま、Windowsへ持ってきたら 動いちゃったよ。

infile = ARGV.shift
KAKASI = 'kakasi -JH -kH -KH -Ea -s -u -osjis'

def say(s)
  fp = IO.popen(KAKASI, 'a+')
    fp.print s
    co = fp.readline
    puts co                              # debug print
    system("jsay #{co.gsub(/ /, '')}")   # call speaker
  fp.close
end

def main(infile)
  puts 'このプログラムは、AquesTalk - テキスト音声合成を利用しています。'
  File.foreach(infile) do |al|
    say(al)
  end
end

main(infile)

上記で、ひらがなになったデータは、co に入っているから、そいつのスペースを削除した上で、 発声ソフトに渡してる。(単なる手抜きで、コマンドライン引数をパースするのが、面倒だった からと言う、脱力系です。)

そうそう、名前重要と言う事で、プログラムに名前を付けてあげないといけないな。 ひらがなを受け取って、発声するソフトは、taro でもいいんだけど、寿命が短そう なので、jsay としたよ。

読み上げ原稿を受け取って、全体をコントロールする(上記のラフスケッチ版)rubyスクリプト は、yomi に、インスパイアーされてるので、妹みたいなものだな。発音 と書いて、 hatune ちょっと長いかな?

この子、おっとりした子で、喋り出すまで、ちと間があるのが難点。後、数字とか アルファベットが途中にあると、貝になってしまいます。このあたりは、もう少し 教育が必要だな。でも、文の終わりを、尻上がりっぽく発音してくれるので、ちょっと かわゆい。

ああ、肝心の、jsayは、実装が変わって、下記のように(今の所)なっています。(世の中では、 これを称して、手抜き工事と言うらしい)

#include <stdio.h>
#include <stdlib.h>
#include "AquesTalkDa.h"

main(int argc, char *argv[]){
    if ( argc != 2){
        printf("もう、hatune 何喋ったらいいか、わかんなーい。\n");
        return 1;
    }
    return AquesTalkDa_PlaySync(argv[1]);
}

使い方は、

c:\sakae\test-kakasi>ruby hatune.rb 原稿.txt
このプログラムは、AquesTalk - テキスト音声合成を利用しています。
こんにちは , あつい よ .
あめ が , ふら ないかなあ .
きょう の ゆうしょく は なにか な .

今日を こんにち と言うのは、辞書を鍛えないとだめだな。それから、 ruby が、そのまま見えるのは、ちょっとカッコ悪いな。後で、batファイルに収納しちゃおう。

兄貴分の yomi について

前回、私のFreeBSD上で、うまく yomi が動かなかった件。作者様に連絡を取った所 至急に対応して頂きました。FreeBSD 7.X で動く版が公開されるはずですので そちらをお使い下さい。

至急の対応、ありがとうございました。