2012年04月25日

Open JTalk を 64ビットWindows用にビルドする方法

Open JTalk を x64 Windows 向けにビルドする方法を調べてみました。

単純にターゲット環境を /MACHINE:x64 のスイッチで64ビットにしてビルドすると、Mecabのコード部分でコンパイルエラーが出ます。feature_index.cppとwrite.cpp です。原因は型の曖昧さエラーです。これを下記のページを参考にしてキャストで型を明示的に指定して解決します。

64ビットWindows用にMeCabをビルドする (Visual Studio 2010を利用)

open_jtalk_1.05 に使われている feature_index.cpp では310行目、write.cpp は235行目が問題の箇所となっています。

feature_index.cpp:310
-            case 't':  os_ << (size_t)path->rnode->char_type;     break;
+            case 't':  os_ << (unsigned int)path->rnode->char_type;     break;

writer.cpp:235
-          case 'L': *os << std::strlen(sentence); break;
+          case 'L': *os << (unsigned int)std::strlen(sentence); break;

とりあえず、これだけの修正でビルドが通ります。しかし、実際に動かすと、応答無しになってしまいます。

VC++でデバッグして調べてみると、hts_engine_API-1.06.tar.gz にある HTS_audio.c の167行目、関数 waveOutOpen 呼び出しでの引数の型が原因だと分かりました。4番目と5番目の引数のキャストを DWORD から DWORD_PTR に変えると、エラーが起きなくなります。DWORDとしてあるのはx64を考慮していない頃の古い定義によるものです。

HTS_audio.c:167
-   error = waveOutOpen(&audio->hwaveout, WAVE_MAPPER, &audio->waveformatex, (DWORD) HTS_Audio_callback_function, (DWORD) audio, CALLBACK_FUNCTION);
+   error = waveOutOpen(&audio->hwaveout, WAVE_MAPPER, &audio->waveformatex, (DWORD_PTR) HTS_Audio_callback_function, (DWORD_PTR) audio, CALLBACK_FUNCTION);

以上、3行修正して、x64向けのビルドをすると、open_jtalk.exe は 64ビットアプリケーションとして動くようになります。

このくらい手作業で十分ですが、折角なので、先日コメント欄で指摘してもらった長文で音声がおかしくなる問題を修正したものも含めて、パッチを三つ作ってみました。

open_jtalk-1.05_x64_patch.zip

patch コマンドがあれば、展開したフォルダに該当するパッチファイルを置いて、例えば、次のコマンドでパッチが当てられます。

patch -p1 < open_jtalk-1.05_x64.patch



posted by takayan at 23:53 | Comment(0) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2012年05月01日

Open JTalk を Windows でビルドするバッチファイル

前回、hts_engine_API の最新バージョンを間違えてしまったので、書き換えたものを作ろうとしたのですが、折角なのでバッチファイルの内部でバージョン番号を書き換えないでいいものを作ったほうが便利そうだったので、そうしてみました。

さらに、以前ソルーションファイルを作って、VC++を起動してビルドできるようにしていましたが、そのファイルも今回の成果をいろいろ追加して入れてみました。VC++2008用ですが、2010で開けば自動的に変換するので利用できます。

ojtalk.bat の仕様も変えて、他の音声に切り替えやすいようにしてみました。あとで説明しますが、音響モデルのフォルダに省略時のパラメータを書いたテキストがあれば、それを使うようにしています。

 

■ ビルド方法

open_jtalk.exe のビルドには、Visual Studio C++ 2010Visual Studio C++ 2008 のどちらかが必要です。2010Express 版でもいいはずです。それからファイルの解凍のために 7zip か tar が必要です。

ファイルは次のリンクからダウンロードします。

openjtalk_buildbatch-003.zip

展開して、そのフォルダに、Open JTalkのビルドに必要な3つのアーカイブを入れます。リンク先から最新版をダウンロードしてください。
open_jtalk-*
hts_voice_nitech_jp_atr503_m001-*
hts_engine_API-*

最初に、prepare.bat を実行します。すると、アーカイブを展開し、インストール先(標準設定でc:\open_jtalk)に、この時点で転送できるファイルを全て転送してくれます。

prepare.bat で準備がすんだら、make.bat を実行します。すると、各フォルダーの Makefile.mak の手順に従い open_jtalk.exe を生成し、インストール先のbinフォルダーに転送します。これで終わりです。

ちゃんと動くかどうかは、インストール先にある ojtalk.bat をダブルクリックして実行すれば確かめられます。「open jtalk」としゃべってくれれば、とりあえずOKです。一度ojtalk.bat を実行すると、インストール先に text.txt が作られるので、このファイルに文章を書き込み、その都度、ojtalk.bat をダブルクリックすると、その内容を読み上げてくれるはずです。

 

■ ソルーションファイル

make.bat を使えば、十分なのですが、open_jtalk\open_jtalk の中にある open_jtalk.sln を使うと、Visual Studio の画面を開いて、ビルドできます。ただし、通常は、ソルーション構成は Release か Debug、ソルーションプラットフォームは Win32 にしてください。必要ないとは思いますが、他の設定を利用するには、prepare.bat の実行前に、 build.info を編集しておく必要があります。

なお、Visual Studio を通して辞書をコンパイルすると相当時間がかかります。気長に待ってください。

 

■ 利用例

今回付属してある ojtalk.bat では、インストール先のvoiceフォルダ(デフォルトだとc:\open_jtalk\voice)に音響モデルのファイルをフォルダごと入れるようにしています。さらにその中に voice.info というファイルがあれば、省略時の -s、-p、-a、-g、-b、-u、-z、-jm、-jf、-jl の値があるとします。mei の利用の仕方は以前紹介しましたが、例えば、フォルダ mei_normal の中に、次の内容の voice.info を入れておきます。

s=48000
z=6000
p=240
a=0.55
jm=0.7
jf=0.5
jl=1.0

音響モデルの指定を –vname でできるようにしたので、次のコマンドで Mei が挨拶します。

ojtalk.bat –vname mei_normal こんにちは

さらに、Windows スクリプティングホスト(wsf) を使うと次のようなこともできます。

<job id="time">
<script language="JScript">
d = new Date();
m = d.getMinutes();
m = (m=="0")?"ちょうど":m+"分";
WScript.CreateObject("WScript.Shell").Run("c:\\open_jtalk\\ojtalk.bat -vname mei_normal "+d.getHours()+"時"+m+"です。",0,true);
</script>
</job>

このような内容の time.wsf というファイルを作って、ダブルクリックすると、時報を伝えてくれます。

さらに、これをインストールしたフォルダに入れておいて、デスクトップにショートカットを作ります。ショートカットを作ると、そのプロパティを開いてショートカットキーも登録できるようになります。例えば、それをCTRL+ALT+Tなどとすると、このショートカットキーがかぶらなければ、このキー操作でいつでも時刻を教えてくれます。またこのスクリプトを、タスクスケジューラに登録して、繰り返し間隔などを設定すれば、定期的に現在時刻を教えてくれるようになります。

 

■ ちょっと複雑な設定

普通に使うならば、上に書いた方法で十分ですが、make.bat でテキストの文字セットを UTF-8 や EUC-JP にしたり、x64向けのビルドをする場合は、build.info を書き換えればできるように作っています。ソルーションファイルを使う場合も同じです。

自動でパッチを当てるときは、パッチを当てるかどうかを「=」の右に文字があるかないかで判断しています。ただこの build.info についての説明はあまり必要ないだろうし、説明も長くなるので割愛します。

 

■ patch コマンドの導入

今回の修正程度ならば、手作業の方が手っ取り早いですが、一応 patch コマンドの導入方法も書いておきます。MinGW/MSYS を利用する方法です。次のサイトから、mingw-get-inst-*.exe という名前のインストーラをダウンロードしてきて実行します。(現時点の最新版は mingw-get-inst-20120426.exe)

MinGW - Minimalist GNU for Windows -  Browse Files at SourceForge.net 

インストール場所は標準のC:\MinGWにします。今回の利用だけならば、コンポーネントは何も選択しなくてもいいです。インストーラの使い方が分からないときは、こちらのサイトに詳しく書いてあります。Windows で MinGW バージョン 20110530 のインストールとテスト実行

インストールが終わったら、次のコマンドを、コマンドプロンプトを開いて実行します。

cd c:\MinGW\bin
mingw-get install msys-patch

これで導入完了。この場所にあれば、PATH を通さなくても、今回のバッチファイルでは patch が実行されるようにしています。ついでに、折角調べたので忘れないように書いておくと tar コマンドは「mingw-get install msys-tar-bin」で入ります。

なお、このように patch コマンドを導入しても、現在のバージョンに対応したパッチが用意されていないと自動でパッチは適用されません。今回用意しているのは、open_jtalk-1.05、hts_engine_API-1.06 向けのパッチです。



posted by takayan at 00:38 | Comment(8) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2012年05月09日

Open JTalk を利用する日本語読み上げ bash スクリプト

先日、Windows 用にバッチファイル ojtalk.bat を作ってみましたが、今度は似たような内容で Linux 用に bash スクリプトを作ってみました。対象は Ubuntu 12.04 と MinGW です。それ以外の場合は、実際にインストールされている場所に DICDIR と VDIRBASE の値を書き換えれば、おそらく動くでしょう。このスクリプトを /usr/local/bin あたりにコピーして使います。

Ubuntu 12.04 では、open-jtalk、open-jtalk-mecab-naist-jdic、hts-voice-nitech-jp-atr503-m001が apt-get や Ubuntuソフトウェアセンターでインストールできるので、それでインストールされているとします。

このスクリプトでは読み上げ文字列の指定は三種類あります。

まず、ちょっとした言葉はコマンドラインに書きます。

ojtalk こんにちは
長い文章の時は、ファイルに utf-8 エンコードで保存して -f オプションで指定します。
ojtalk -f hoge.txt
標準入力を読ませたいときは、文字を付けない '-' をコマンドラインに置きます。
cat hoge.txt|ojtalk -
上記の読み上げ文字列の指定が複数あるときは、左から順に処理します。ただし文字列の合計の長さは bash の限界までです。

その他に、音声ファイルを作るときは、-ow hoge.wav とします。このとき、しゃべらせたくないときは、-quiet も一緒に指定します。hts-voice フォルダに他の音声データが入っているときは -vname mei_normal といった感じで音声を替えられます。このとき、その中に voice.info ファイルが入っていると、その情報を参照します。

さて、以前からの課題である GNOME orca の日本語化の件ですが、この bash スクリプトを使えば、python から次の形で呼び出せますから、以前よりシンプルに作れると思います。

os.system(u'ojtalk こんにちは'.encode('utf8'))

まず、このスクリプトを利用したものを作ってから、そのあとで Speech Dispatcher 経由のものを考えることにします。

以下、ojtalk ソース:

#!/bin/bash

if [ `uname|grep "MINGW"` ]; then
	DICDIR=/usr/local/dic
	VDIRBASE=/usr/local/hts-voice
	DEFAULT_VOICE_NAME=hts_voice_nitech_jp_atr503_m001
	mingw=1
else
	DICDIR=/var/lib/mecab/dic/open-jtalk/naist-jdic
	VDIRBASE=/usr/share/hts-voice
	DEFAULT_VOICE_NAME=nitech-jp-atr503-m001
	mingw=0
fi

# default parameters
MESSAGE='open jtalk'
S=48000
P=240
A=0.55
G=0
B=0.0
U=0.5
Z=1600
JM=1.0
JF=1.0
JL=1.0
MEI_S=48000
MEI_P=240
MEI_A=0.55
MEI_G=0
MEI_B=0.0
MEI_U=0.5
MEI_Z=6000
MEI_JM=0.7
MEI_JF=0.5
MEI_JL=1.0

if [ $mingw == 1 ]; then
	CURDIR=`dirname $0`
	TEMPTXTFILE=$CURDIR/_text.txt
	TEMPWAVFILE=$CURDIR/_wave.wav
else
	TEMPTXTFILE=$(mktemp /tmp/ojtalk_txt_XXXXXXXX)
	TEMPWAVFILE=$(mktemp /tmp/ojtalk_wav_XXXXXXXX)
fi

L_SWITCH=
QUIET_SWITCH=0
VNAME_VALUE=
VDIR_VALUE=
S_VALUE=
P_VALUE=
A_VALUE=
G_VALUE=
B_VALUE=
U_VALUE=
Z_VALUE=
JM_VALUE=
JF_VALUE=
JL_VALUE=
OT_VALUE=/dev/null
OW_VALUE=
TEXT=

error(){
	cmd=`basename $0`
	message="Bad parameter!"
	if [ "$1" ]; then message=$1; fi
	echo "$cmd: $message";
	exit 1;
}

if [ ! -d $DICDIR ]; then
	error "No dic directory : $DICDIR"
fi

if [ ! -d $VDIRBASE ]; then
	error "No voice directory : $VDIRBASE"
fi

while [ $1 ]; do
	if [ $1 == -l ]; then
		L_SWITCH=-l
	elif [ $1 == - ]; then
		data=$(tr '\n\r' '  ')
		TEXT="$TEXT $data"
	elif [ $1 == -vname ]; then
		shift
		if [ ! $1 ]; then error; fi
		VNAME_VALUE=$1
	elif [ $1 == -vdir ]; then
		shift
		if [ ! $1 ]; then error; fi
		VDIR_VALUE=$1
	elif [ $1 == -quiet ]; then
		QUIET_SWITCH=1
	elif [ $1 == -f ]; then
		shift
		if [ ! $1 ]; then error; fi
		if [ -f $1 ]; then
			data=$(cat $1|tr '\n\r' '  ')
			TEXT="$TEXT $data"
		else
			error "No text file: $1"
		fi

	elif [ $1 == -ow ]; then
		shift
		if [ ! $1 ]; then error; fi
		OW_VALUE=$1
	elif [ $1 == -ot ]; then
		shift
		if [ ! $1 ]; then error; fi
		OT_VALUE=$1
	elif [ $1 == -s ]; then
		shift
		if [ ! $1 ]; then error; fi
		S_VALUE=$1
	elif [ $1 == -p ]; then
		shift
		if [ ! $1 ]; then error; fi
		P_VALUE=$1
	elif [ $1 == -a ]; then
		shift
		if [ ! $1 ]; then error; fi
		A_VALUE=$1
	elif [ $1 == -g ]; then
		shift
		if [ ! $1 ]; then error; fi
		G_VALUE=$1
	elif [ $1 == -b ]; then
		shift
		if [ ! $1 ]; then error; fi
		B_VALUE=$1
	elif [ $1 == -u ]; then
		shift
		if [ ! $1 ]; then error; fi
		U_VALUE=$1
	elif [ $1 == -jm ]; then
		shift
		if [ ! $1 ]; then error; fi
		JM_VALUE=$1
	elif [ $1 == -jf ]; then
		shift
		if [ ! $1 ]; then error; fi
		JF_VALUE=$1
	elif [ $1 == -jl ]; then
		shift
		if [ ! $1 ]; then error; fi
		JL_VALUE=$1
	elif [ $1 == -z ]; then
		shift
		if [ ! $1 ]; then error; fi
		Z_VALUE=$1
	else
		TEXT="$TEXT $1"
	fi
	shift
done

if [ ! $VDIR ]; then
	if [ $VNAME_VALUE ]; then
		VDIR=$VDIRBASE/$VNAME_VALUE
	else
		VDIR=$VDIRBASE/$DEFAULT_VOICE_NAME
	fi
fi
if [ ! -d $VDIR ]; then
	error "No voice directory : $VDIR"
fi

if [ -f $VDIR/voice.info ]; then
	while read line; do
		if [[ $line =~ ^MESSAGE= ]]; then
			MESSAGE=`echo $line|sed "s/^MESSAGE=//"`
		fi
		if [[ $line =~ ^s=  ]]; then
			S=`echo $line |sed "s/^s=//"`
		fi
		if [[ $line =~ ^p=  ]]; then
			P=`echo $line |sed "s/^p=//"`
		fi
		if [[ $line =~ ^a=  ]]; then
			A=`echo $line |sed "s/^a=//"`
		fi
		if [[ $line =~ ^g=  ]]; then
			G=`echo $line |sed "s/^g=//"`
		fi
		if [[ $line =~ ^b=  ]]; then
			B=`echo $line |sed "s/^b=//"`
		fi
		if [[ $line =~ ^u=  ]]; then
			U=`echo $line |sed "s/^u=//"`
		fi
		if [[ $line =~ ^z=  ]]; then
			Z=`echo $line |sed "s/^z=//"`
		fi
		if [[ $line =~ ^jm= ]]; then
			JM=`echo $line |sed "s/^jm=//"`
		fi
		if [[ $line =~ ^jf= ]]; then
			JF=`echo $line |sed "s/^jf=//"`
		fi
		if [[ $line =~ ^jl= ]]; then
			JL=`echo $line |sed "s/^jl=//"`
		fi
	done < $VDIR/voice.info
fi

if [[ $VNAME_VALUE =~ ^mei_ ]]; then
	if [ ! $S_VALUE  ]; then  S_VALUE=$MEI_S;  fi
	if [ ! $P_VALUE  ]; then  P_VALUE=$MEI_P;  fi
	if [ ! $A_VALUE  ]; then  A_VALUE=$MEI_A;  fi
	if [ ! $G_VALUE  ]; then  G_VALUE=$MEI_G;  fi
	if [ ! $B_VALUE  ]; then  B_VALUE=$MEI_B;  fi
	if [ ! $U_VALUE  ]; then  U_VALUE=$MEI_U;  fi
	if [ ! $Z_VALUE  ]; then  Z_VALUE=$MEI_Z;  fi
	if [ ! $JM_VALUE ]; then JM_VALUE=$MEI_JM; fi
	if [ ! $JF_VALUE ]; then JF_VALUE=$MEI_JF; fi
	if [ ! $JL_VALUE ]; then JL_VALUE=$MEI_JL; fi
else
	if [ ! $S_VALUE  ]; then  S_VALUE=$S;  fi
	if [ ! $P_VALUE  ]; then  P_VALUE=$P;  fi
	if [ ! $A_VALUE  ]; then  A_VALUE=$A;  fi
	if [ ! $G_VALUE  ]; then  G_VALUE=$G;  fi
	if [ ! $B_VALUE  ]; then  B_VALUE=$B;  fi
	if [ ! $U_VALUE  ]; then  U_VALUE=$U;  fi
	if [ ! $Z_VALUE  ]; then  Z_VALUE=$Z;  fi
	if [ ! $JM_VALUE ]; then JM_VALUE=$JM; fi
	if [ ! $JF_VALUE ]; then JF_VALUE=$JF; fi
	if [ ! $JL_VALUE ]; then JL_VALUE=$JL; fi
fi

if [ "$TEXT" ]; then
	echo $TEXT>$TEMPTXTFILE
else
	echo $MESSAGE>$TEMPTXTFILE
fi
if [ ! -f $TEMPTXTFILE ]; then
	error "No temp file : $TEMPTXTFILE"
fi

open_jtalk \
-x  $DICDIR \
-td $VDIR/tree-dur.inf \
-tm $VDIR/tree-mgc.inf \
-tf $VDIR/tree-lf0.inf \
-tl $VDIR/tree-lpf.inf \
-md $VDIR/dur.pdf \
-mm $VDIR/mgc.pdf \
-mf $VDIR/lf0.pdf \
-ml $VDIR/lpf.pdf \
-dm $VDIR/mgc.win1 \
-dm $VDIR/mgc.win2 \
-dm $VDIR/mgc.win3 \
-df $VDIR/lf0.win1 \
-df $VDIR/lf0.win2 \
-df $VDIR/lf0.win3 \
-dl $VDIR/lpf.win1 \
-ow $TEMPWAVFILE \
-ot $OT_VALUE \
-s  $S_VALUE \
-p  $P_VALUE \
-a  $A_VALUE \
-g  $G_VALUE \
-b  $B_VALUE \
$L_SWITCH \
-u  $U_VALUE \
-em $VDIR/tree-gv-mgc.inf \
-ef $VDIR/tree-gv-lf0.inf \
-cm $VDIR/gv-mgc.pdf \
-cf $VDIR/gv-lf0.pdf \
-jm $JM_VALUE \
-jf $JF_VALUE \
-jl $JL_VALUE \
-k  $VDIR/gv-switch.inf \
-z  $Z_VALUE \
$TEMPTXTFILE

if [ $mingw == 0 ]; then
	if [ -f "$TEMPWAVFILE" ]; then
		if [ $QUIET_SWITCH == 0 ]; then
			aplay -q $TEMPWAVFILE
		fi
	fi
fi
if [ "$OW_VALUE" ]; then
	cp $TEMPWAVFILE $OW_VALUE
fi
rm -f $TEMPWAVFILE
rm -f $TEMPTXTFILE

exit 0


posted by takayan at 02:30 | Comment(0) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2013年01月25日

htsvoiceへ変換するプログラム

今回はひさしぶりに Open JTalk 関連です。

旧式の hts_engine_API 用の音響モデルの設定ファイル群を htsvoiceフォーマットのファイルに変換する実行ファイルを作ってみました。

必要な方は以下のリンクからダウンロードできます。自己責任でお使いください。

ダウンロード: htsvconv002.zip

(更新2013/02/09:config.txt がそばに無いとき、alphaを標準値にする処理が抜けていたので修正しました。)

内容物は、htsvconv.exe、config.txt、htsvconv.cs、test.bat の4つです。実際に必要なのは htsvconv.exe のみで、必要に応じてパラメータを初期値から変更するためのファイルconfig.txt、C#ソースファイルhtsvconv.cs、そして実際に声が出るかテストするためのWindows用バッチファイルです。

コマンドラインから、

htsvconv {ファイル群のあるフォルダ名}

で使います(上記の{}は省略可能かつ繰り返し可能の意味)。マウス操作のときはhtsvconv.exe の上に音声ファイル群のあるフォルダを重ねて落として使います。うまくいくとhtsvconv .exeと同じ場所にそのフォルダ名に.htsvoiceを付けたファイルが生成されます。なおパラメータ無しで実行すると、htsvconv .exeと同じ場所にファイル群があるとみなして処理を始めます。

exeファイルなのでWindows限定かというとそうでもありません。mono 環境下での実行もコンパイルも問題ないはずです。環境が整っていれば、Windows 以外でも実行できるはずです。

htsvoiceフォーマットはいくつかのパラメータを内部に持つことができます。特に重要なのがSAMPLING_FREQUENCYとFRAME_PERIODです。また、OPTIONパラメータとして、ALPHA、GAMMA
LN_GAINの値も記述できます。

htsvconv.exe のあるフォルダに config.txt というファイルを入れておくと、そこに書いてある定数をhtsvoiceに埋め込むようにしています。表記法は「定数名=値」です。一行に一つの式です。指定が無ければ標準値SAMPLING_FREQUENCY=48000、FRAME_PERIOD=240、ALPHA=0.55が使われます。

Windows版 のopen_jtalk.exe 1.06の作成は、以前公開したビルドバッチで生成できます。ただし修正パッチなどは今回のバージョン向けに作っていないので、64ビットなどの特殊なビルドはできません。またopen_jtalkのオプションが変わっているので、ojtalk.bat による発声もできません。

今回のアーカイブはそのビルドバッチでできたvoiceフォルダに直接それぞれのファイルを展開すると使いやすいようにしています。音声が使えるか試すための test.bat はvoiceフォルダから使うことを前提として書いています。内容は以下の通りです。ディレクトリの構成が違うときは必要に応じて内容を書き換えます。

set VOICE=hts_voice_nitech_jp_atr503_m001\nitech_jp_atr503
rem set VOICE=mei_normal
..\bin\open_jtalk -x ..\dic -m ..\voice\%VOICE%.htsvoice -z 2000 ..\text.txt

mei の各音声と nitech_jp_atr503_m001 バージョン1.04での変換は確認できましたが、それ以外のデータでの動作は分かりません。うまくいかないときはソースを修正しビルドし直して対応するか、あきらめてください。

ソースのビルドは、.NET Framework だと 「csc htsvconv.cs」、mono だと 「mcs htsvconv.cs」 です。

 

以下、制作動機など:

上記のopen jtalk というのは、オープンソースの音声合成エンジンです。WindowsやLinuxなどでそれなりの技術があれば無料でパソコンに言葉をしゃべらせられるようになります。おもしろそうだったので何度かここで紹介してきました。毎年恒例ですが年末に最新版1.06が出ました。

今回のバージョンアップで一番の変化は、hts_engine_APIの仕様が変わったのに伴い、音声データのフォーマットが変わったことです。いままでは、音声についての設定が複数のファイルに分かれていたので、これをコマンドラインのオプションスイッチで20個くらいのファイルを一つ一つ指定しなくてはいけなくて、設定がとてもわかりにくかったのですが、1.06から-mスイッチでファイルを一つ指定するだけになりました。

ただ、このフォーマットの日本語の音響モデルのデータは、2013/01/25現在、標準音声の hts_voice_nitech_jp_atr503_m001 だけしかありません。今までは MMDAgent_Example に入っている mei_normal などを転用できたのですが、mei の htsvoice 版のデータはまだ出ていないようです。待っていれば、いずれは正式に出てくるでしょう。待っていれば、いずれはね。

でも待ちきれなかったので、作ってみました、変換器。新しい nitech_jp_atr503_m001.htsvoice を使った音声を聞いてみても、ほとんど違いは分からなかったので、おそらくデータそのものは同じで、格納方法が変更になっただけだろうと予想を立てて、新旧のHTS_model.cでの処理の違いを調べ、htsvoiceファイルへの変換器を作ってみました。言語はC#。

公式の htsvoice フォーマットの音声が出てくるのは時間の問題だと思いますので、とりあえずそれまでのつなぎということで。

 

関連リンク:
Open JTalk 公式サイト、Open Jtalk のダウンロードはここから。
mmdagent.jp MMDAgentの公式サイト
mono 公式サイト。Windows以外で利用するときは、この mono の環境があれば実行できます。
まほろば::オープンソース音声合成エンジン「Open JTalk 1.06」  ビルドの方法やテストの仕方があります

当ブログ関係記事:
Open JTalk を Windows でビルドするバッチファイル



posted by takayan at 22:45 | Comment(15) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2013年02月09日

open jtalk 1.06 を VS2012で ビルドするバッチ

open Jtalk をビルドするバッチを更新しました。(以前の記事

open Jtalkがバージョンアップしても書き換えなくていいように内部で複雑なことをしていたのですが、open Jtalk 1.06で音響モデルファイルの構成が変わってしまったので、細かなところがうまくいかなってしまいました。最初はいいアイデアだと思ったのですが、こういう自動化よりも、年に一度その都度、ファイル名や処理を書き換えてシンプルなバッチを書いてビルドするのがベストですね。

でも今回はちょっと意地になって対応してみることにしました。ついでに Windows 8 に合わせて去年登場した Visual Studio Express 2012 for Windows Desktop でもビルドできるようにしてみました。他にVC++2008とVC++2010Expressでできるはずです。

ダウンロード: openjtalk_buildbatch-005.zip

MD5:7789eb6a3270eefbadaf827df6028417

(Open JTalk 1.07及びVS2013への対応 2013.12.31更新)

使い方は以前の通りですので、「Open JTalk を Windows でビルドするバッチファイル」を見てください。上記ファイルを展開して、そのフォルダ内にopen jtalk関連のアーカイブを入れ、必要ならばbuild.info でパッチの実の指示をして、prepare.batを実行し、make.batを実行すれば、標準設定ならば、c:\open_jtalk\bin\にopen_jtalk.exeができあがります。c:\open_jtalk\ojtalk.batを使うか、次のようなバッチファイルを実行すると、確認できます。

set MESSAGE=こんにちは
set VOICE=nitech_jp_atr503_m001
cd c:\open_jtalk
(echo %MESSAGE%)>text.txt
bin\open_jtalk -x dic -m voice\%VOICE%.htsvoice -z 6000 text.txt

以前の記事に書いていない主な変更点として、build.infoファイルでパッチを当てるかどうかのフラグとしてPATCH_OPEN_JTALK_MAKE_PAIRを追加しています。右辺に何か文字があると、下記で説明している、open Jtalk 1.05 を VC++ 2012でビルドするためのパッチを当てます。

明記したほうがいいものをいくつか書いておきます。

x64向けにビルドしようとすると、今回から音響モデルデータが htsvoice 形式になったため、今までとは違う原因で hts_engine_API 内でコンパイルエラーや実行時エラーになってしまいます。今のところOpen JTalk をx64でビルドするメリットはありませんが、コンパイルが通らないと無性にその原因を調べたくなるものです。そして、たいていこういうのは ポインタやsize_t 自身のサイズです。具体的には、HTS_Model構造体npdfの型を size_t* からunsigned int*に変えています。また、waveOutOpenのコールバック関数の型のいくつかをDWORDからDWORD_PTRに書き換えます。

それから、htsvoice ファイルをvoiceフォルダの中に直接置くようにしています。たくさんのファイルが必要だったときはvoiceフォルダの中にそれらのファイルが収まったフォルダを置いていましたが、必要なのがhtsvoice ファイルだけなので、アーカイブから抽出してそれだけを置いています。なお、以前の方式の音響モデルデータファイルから、htsvoice ファイルへの変換は htsvconv.exe でできます。Windowsならばhtsvconv.exeの上にマウスでフォルダを落とせば生成されます。

新しいものがあるので、古い Open Jtalk 1.05 を使う必要も無いかもしれませんが、以前の音響データを使うときのためにこれもビルドできるようにしてあります。ただし、open Jtalk 1.05 を VC++ 2012 でビルドしようとするとエラーが出ます。 原因はC++11標準の影響で std::make_pair の明示的なテンプレート引数に関する扱いが変わったためです。これに対応するパッチも作りました。パッチファイルは open_jtalk-1.05_make_pair.patch です。

-      category.insert(std::make_pair<std::string,charinfo>(key,c));
+      category.insert(std::pair<std::string,charinfo>(key,c));

こんな感じです。

build.infoファイルで次のように記述してあると、自動的にopen Jtalk 1.05にパッチをあてるようにしてあります。もちろん patch コマンドがインストールされている必要があります。

PATCH_OPEN_JTALK_MAKE_PAIR=ON

なお1.06では既にこの部分を置き換えてある mecab のコードを利用しているので修正の必要ありません。

他に新しくやったこととして内部での作業で文字列置換の標準入出力のフィルタがほしかったので、rplc.exeというコマンドを作って利用しています。具体的には、プリプロセッサマクロの定義をバッチファイルだけで書き換えるのが難しかったので、mecab\mecab.vcproj 内で@VERSION@をrplc.exeを使って処理対象のバージョンに書き換えています。



posted by takayan at 15:01 | Comment(0) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2013年12月31日

Open JTalk 1.07 をいろいろビルドしてみました。

毎年恒例のOpen JTalkのクリスマスのバージョンアップが今年も行われました。今まで通りにできるかどうか確認してみました。

■ Ubuntu 13.10

まずubuntu 13.10 64ビット版と32ビット版でやってみました。以前のバージョンのhts_engine_API-1.07には64ビット環境ではhtsvoiceファイルのデータの読み込みに問題があって、ここで公開していたパッチをあてたりしないとうまくいきませんでしたが、今回は確かに修正なしでビルドできました。

実際の手順ですが、Open JTalk からhts_engine_API-1.08.tar.gz、open_jtalk-1.07.tar.gzそして、hts_voice_nitech_jp_atr503_m001-1.05.tar.gzの3つのファイルをダウンロードします。

hts_engine_API-1.08、次にopen_jtalk-1.07に対して、それぞれ展開し、フォルダ内で、お決まりの次のコマンドを実行します。

./configure 
make
sudo make install

インストール先やopen_jtalkの辞書の文字コードなどを変えるときは、./configure のオプションを使います。

標準では、実行ファイルは/usr/local/binに、辞書は/usr/local/dicに入ります。hts_voice_nitech_jp_atr503_m001-1.05.tar.gzファイル内のhtsvoiceファイルはこれに合わせて、分かりやすく/usr/local/voice/に置きます。

簡単な動作確認は次のようにします。test.txtに1行書いて、辞書の文字コードと同じエンコードでドキュメントフォルダーなど適当なところに保存します。標準では辞書のエンコードははEUC-JPですね。そしてtext.txtを保存した場所で次のコマンドを実行すれば、同じ場所に音声ファイルが作成されるはずです。

open_jtalk -x /usr/local/dic -m /usr/local/voice/nitech_jp_atr503_m001.htsvoice -z 6000 -ow out.wav test.txt 

ただ、当初からの問題ですが、標準のhtsvoice音響モデルファイルm001で長文を読ませると、やはり不安定になります。以下に示すどのような環境でのビルドでもこの問題は出てきます。mei_normalなど他の音響モデルでは別に問題にはなりません。

このm001が不安定になる問題の回避策としてOpen JTalk [ja.nishimotz.com]でjpcommon_label.cの修正が示されていますが、今回のバージョンで対応する変更箇所は以下のとおりになります。

diff -ru open_jtalk-1.07_original/jpcommon/jpcommon_label.c open_jtalk-1.07/jpcommon/jpcommon_label.c
--- open_jtalk-1.07_original/jpcommon/jpcommon_label.c	2013-12-24 23:25:41 +0900
+++ open_jtalk-1.07/jpcommon/jpcommon_label.c	2013-12-26 00:29:04 +0900
@@ -296,6 +296,7 @@
       if (index == a)
          break;
    }
+   if (i > 3) i = 3;
    return i;
 }
 
@@ -395,6 +396,7 @@
 
    for (i = 0, index = m->next; index != NULL; index = index->next)
       i++;
+   if (i > 10) i = 10;
    return index_mora_in_utterance(m) + i;
 }

 

Windows 8.1 (64ビット)でもビルドできるか試してみました。

■ VC++

まず、マイクロソフトのVC++でやってみました。VC++は最新の「Visual Studio Express 2013 for Windows Desktop」の無料で使えるExpressエディションのもので試しました。結果は、通常のビルドは問題ありませんでした。

Express版は次のリンク先からダウンロードして、インストールします。手順はリンク先に書いてあるので、ここでは割愛します。

Microsoft Visual Studio Express 2013 for Windows Desktop

VC++インストール後、64ビットOSではhts_engine_API-1.08.tar.gzとopen_jtalk-1.07.tar.gzを展開したそれぞれのフォルダ内で、次のコマンドを実行すれば、ビルドできます。インストール先は標準設定でc:\open_jtalkになります。

call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
nmake -f Makefile.mak
nmake -f Makefile.mak install

※32ビットWindowsの場合はProgram Files (x86)をProgram Filesにする。

hts_voice_nitech_jp_atr503_m001-1.05.tar.gzの中にあるhtsvoiceファイルがc:\open_jtalk\voiceフォルダに入れてあるとすると、次のようなコマンドで確認できます。Ubuntuでやったときと違い、これだけで音声を発します。

echo こんにちは >test.txt
c:\open_jtalk\bin\open_jtalk -x c:\open_jtalk\dic -m c:\open_jtalk\voice\nitech_jp_atr503_m001.htsvoice -z 6000 test.txt

このExpress版には、64ビットアプリケーションをビルドするためにクロスコンパイラも付属しています。しかしこの機能を使って64ビットアプリケーションを作るには修正が必要でした。

まず、hts_engine_API-1.08についてですが、これは前も指摘したことがあるwaveOutOpenに関連する修正です。

diff -ru hts_engine_API-1.08_original/lib/HTS_audio.c hts_engine_API-1.08/lib/HTS_audio.c
--- hts_engine_API-1.08_original/lib/HTS_audio.c	2013-12-24 23:22:44 +0900
+++ hts_engine_API-1.08/lib/HTS_audio.c	2013-12-28 16:11:17 +0900
@@ -85,7 +85,7 @@
 } HTS_AudioInterface;
 
 /* HTS_AudioInterface_callback_function: callback function from audio device */
-static void CALLBACK HTS_AudioInterface_callback_function(HWAVEOUT hwaveout, UINT msg, DWORD user_data, DWORD param1, DWORD param2)
+static void CALLBACK HTS_AudioInterface_callback_function(HWAVEOUT hwaveout, UINT msg, DWORD_PTR user_data, DWORD_PTR param1, DWORD_PTR param2)
 {
    WAVEHDR *wavehdr = (WAVEHDR *) param1;
    HTS_AudioInterface *audio_interface = (HTS_AudioInterface *) user_data;
@@ -177,7 +177,7 @@
    audio_interface->waveformatex.nBlockAlign = AUDIO_CHANNEL * audio_interface->waveformatex.wBitsPerSample / 8;
    audio_interface->waveformatex.nAvgBytesPerSec = sampling_frequency * audio_interface->waveformatex.nBlockAlign;
    /* open */
-   result = waveOutOpen(&audio_interface->hwaveout, WAVE_MAPPER, &audio_interface->waveformatex, (DWORD) HTS_AudioInterface_callback_function, (DWORD) audio_interface, CALLBACK_FUNCTION);
+   result = waveOutOpen(&audio_interface->hwaveout, WAVE_MAPPER, &audio_interface->waveformatex, (DWORD_PTR) HTS_AudioInterface_callback_function, (DWORD_PTR) audio_interface, CALLBACK_FUNCTION);
    if (result != MMSYSERR_NOERROR) {
       HTS_error(0, "hts_engine: Failed to open your output audio_interface device to play waveform.\n");
       HTS_free(audio_interface);

一方、open_jtalk-1.07ではMeCabの以下の部分です。これは以前から知られているMeCabの修正です。「MeCab を MinGW-w64 でビルド。ついでに、Java バインディングもビルド」 を参考にC++らしい型キャストにしてみました。

diff -ru open_jtalk-1.07_original/mecab/src/feature_index.cpp open_jtalk-1.07/mecab/src/feature_index.cpp
--- open_jtalk-1.07_original/mecab/src/feature_index.cpp	2013-12-11 14:56:19 +0900
+++ open_jtalk-1.07/mecab/src/feature_index.cpp	2013-12-30 23:18:15 +0900
@@ -353,7 +353,7 @@
               if (!r) goto NEXT;
               os_ << r;
             } break;
-            case 't':  os_ << (size_t)path->rnode->char_type;     break;
+            case 't':  os_ << static_cast<unsigned int>(path->rnode->char_type);     break;
             case 'u':  os_ << ufeature; break;
             default:
               CHECK_DIE(false) << "unknown meta char: " <<  *p;
diff -ru open_jtalk-1.07_original/mecab/src/writer.cpp open_jtalk-1.07/mecab/src/writer.cpp
--- open_jtalk-1.07_original/mecab/src/writer.cpp	2013-12-11 14:56:22 +0900
+++ open_jtalk-1.07/mecab/src/writer.cpp	2013-12-30 23:16:25 +0900
@@ -257,7 +257,7 @@
             // input sentence
           case 'S': os->write(lattice->sentence(), lattice->size()); break;
             // sentence length
-          case 'L': *os << lattice->size(); break;
+          case 'L': *os << static_cast<unsigned int>(lattice->size()); break;
             // morph
           case 'm': os->write(node->surface, node->length); break;
           case 'M': os->write(reinterpret_cast
これらの修正を行った後、hts_engine_APIから順にそれぞれの展開したフォルダ内で次のコマンドを実行するとビルドできました。
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64 
nmake -f Makefile.mak 
nmake -f Makefile.mak install

必要性はほとんどないでしょうが、Program Files (x86) をProgram Filesに書き換えれば、32ビットパソコンでとりあえず64ビットの実行ファイルを作ることができます(もちろん実行はできませんが)。ただし、辞書のコンパイルのとき、作成したばかりの64ビット向けのコマンドを実行しようとしてエラーを出すので、辞書は32ビットのコマンドで作るか公式サイトからダウンロードしてくる必要があります。

 

■ Windows 8.1上の Cygwin, Mingw

cygwin、mingwでもビルドしてみました。Mingwは以前mingw-get-instで作った環境ではうまくできたのですが、再現性を確保するために、現在の mingw-get-setupを使って環境を作ろうとしましたが、どうしても作れませんでした。仕方がないので、cygwinでmingwのコンパイラを使って作りました。

前提となる、Cygwinの環境作りですが、Cygwinのサイトから、setup-x86.exeかsetup-x86_64.exeをダウンロードして、インストールします。詳しいインストールの仕方はここでは割愛します。ダウンロード先にある説明を読むか、割と新しいマイナビニュースの記事などを参考にしてください。今回のビルドを行うには、最低、makeとgcc-coreとgcc-g++の3つのパッケージが必要です。またmingwでコンパイルを行う場合は、さらに対応するgccとg++を入れます。具体的には、32ビットアプリケーションに必要なのがmingw64-i686-gcc-coreとmingw64-i686-gcc-g++で、64ビットアプリケーション向けはmingw64-x86_64-gcc-coreとmingw64-x86_64-gcc-g++です。

まず、Cygwinのコンパイラを使った場合ですが、32ビットアプリケーションを作る場合はソースの修正は必要ありませんでした。しかし64ビットアプリケーションを作るときは、コンパイルは何事もなく完了するのですが、実行すると異常終了しました。原因は上記VC++と同様で、hts_engine_API-1.08のファイルに上記の修正をします。一方のopen_jtalk-1.07のファイルに関しては修正は必要ありませんでした。

hts_engine_API-1.08とopen_jtalk-1.07とそれぞれの展開した先で次のコマンドを実行します。

./configure
make
make install

なお、文字コードは標準ではEUCになってしまいますが、WindowsではシフトJISの方が今でもなにかと都合がいいので、open_jtalk-1.07をビルドするときは、./configure –with-charset=SHIFT_JISとした方がいいかもしれません。

次に、Mingw向けのビルドです。これは少し修正が必要でした。

64ビットアプリケーションを作る場合、hts_engine_API-1.08のファイルに上記の修正が必要でした。そしてopen_jtalk-1.07のファイルはCygwinと違って、Windowsのときと同様の修正が必要でした。

※下の打ち消し線の部分の代わりの記事は、下方の「■追記(2014/02/01)」のところ書いています。

さらに、これは32ビット向けの場合も含めて、open_jtalk-1.07のファイルのMeCabの部分にあるプリプロセッサ命令の定数__CYGWIN__を__MINGW32__を置き換えます。これは完全な解決法ではありません。本来は一つ一つ確認して是非を確認すべきですし、置き換えではなく、条件文に__MINGW32__の項目を追加したほうがいいのですが、とりあえずうまくうまくいきました。

実際には、open_jtalk-1.07/mecab/src に入って次のコマンドで一気に置き換えました

find . -type f | xargs sed -i 's/__CYGWIN__/__MINGW32__/g'

それから、ビルド中の辞書のコンパイルにおいて、生成したばかりの実行ファイルを使いますが、このときdllが見つからずにコンパイルが止まってしまいます。それを防ぐために、予めパスに追加しておきます。

32ピットアプリケーションを作るときは、こんな感じ、

export PATH=$PATH:/usr/i686-w64-mingw32/sys-root/mingw/bin

64ピットアプリケーションを作るときは、こんな感じです。

export PATH=$PATH:/usr/x86_64-w64-mingw32/sys-root/mingw/bin

準備が整ったら、今までと同じように、hts_engine_API-1.08から先に展開したそれぞれのフォルダ内で以下のコマンドを実行します。以下に示すのは64ビットアプリケーションを作る例です。32ビットの場合はそれぞれの=の後はi686-w64-mingw32にします。

./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32
make
make install

ここで作られた実行ファイルは残念ながらlibstdc++-6.dllやlibgcc_s_seh-1.dllもしくはlibgcc_s_sjlj-1.dllが必要になっています。これを静的リンクにする方法はあるみたいですが、よくわからなかったので、今回そこまでできませんでした。

(2014.01.11追記) configure を実行する前に、C コンパイラを次のように定義するとスタティックリンクになります。

export CC="x86_64-w64-mingw32-gcc -static"

なおこれは64bitアプリケーションを作る場合です。32ビットアプリケーションはi686-w64-mingw32-gccに置き換えます。できた実行ファイルは今回13126kBととても大きくなりましたが、stripコマンドでスリムにすると1159kBになりました。(追記終わり)

 

以前Windowsでのビルドをやってくれるバッチファイルを作りました(「open jtalk 1.06 を VS2012で ビルドするバッチ」)。特に設定を変えなければ、今回のものもビルドできました。そのままでもよかったのですが、上記で紹介したパッチを含めて、いくつかの細かな修正をしたものを今回新しく作りました。使い方は以前と同じなので、こちらで確認ください。上に示したようにがシフトJIS向けのビルドは上記のたった三行でビルド可能なので、あくまでも参考までにご使用ください。

ダウンロード:openjtalk_buildbatch-005.zip
(MD5: 7789eb6a3270eefbadaf827df6028417)

最後に、Open JTalkとともに、MMDAgentも更新がありました。その関連アーカイブのMMDAgent_Example-1.4.zipにmeiのhtsvoiceファイルが入りました。これを手に入れるために、今年の初めに旧形式からの変換器htsvconvを作ったわけですが、確認したらバイナリ的に同一のものなので、htscnvの変換結果は正解ということで、いいですね。

■追記(2014/02/01)

mingwへの対応があまりにも大雑把なので修正しておきます。今回のopen_jtalkで使われているMeCabのバージョンは最新のものの一つ前の0.994です。0.99系列でWindows版のMeCabはユニコード正式対応になったのですが、このときの大幅な変更により、mingwでまともなコンパイルができなくなってしまいました。この問題はまだ解決はしていません。一番有益な情報は、mecab-develメーリングリストの97番の投稿です。

MeCabのmingwに関する現状はそうなのですが、open_jtalkに使われているMeCabはちょっと事情が違います。open_jtalkの辞書はまだユニコード対応ではなく、UTF-8を含むマルチバイト文字コードのままなので、ユニコード対応部分を丸ごとすっ飛ばしても関係ありません。それを簡潔に、cygwinのコンパイラ向けの回避策をそのまま使って実現したのが、前回の__CYGWIN__を__MINGW32__による置換というわけです。

自分がmingwでのコンパイルに興味がなかったので、深く掘り下げませんでした。でも、やはりこれは手抜き過ぎる解決策です。最小限の変更箇所のパッチを作ってみました。open_jtalk-1.07_mingw.patch

diff -ru open_jtalk-1.07.orig/mecab/src/common.h open_jtalk-1.07/mecab/src/common.h
--- open_jtalk-1.07.orig/mecab/src/common.h	2013-12-11 14:56:17 +0900
+++ open_jtalk-1.07/mecab/src/common.h	2014-02-01 17:20:15 +0900
@@ -144,7 +144,7 @@
 #define EXIT_SUCCESS 0
 #endif
 
-#if defined(_WIN32) && !defined(__CYGWIN__)
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__)
 #define WPATH(path) (MeCab::Utf8ToWide(path).c_str())
 #else
 #define WPATH(path) (path)
diff -ru open_jtalk-1.07.orig/mecab/src/thread.h open_jtalk-1.07/mecab/src/thread.h
--- open_jtalk-1.07.orig/mecab/src/thread.h	2013-12-11 14:56:21 +0900
+++ open_jtalk-1.07/mecab/src/thread.h	2014-02-01 17:20:15 +0900
@@ -85,13 +85,20 @@
 
 namespace MeCab {
 
+#ifdef __MINGW32__
+#if defined(__i386__) && !defined(__x86_64) && !defined(__SSE2__)
+#undef YieldProcessor
+#define YieldProcessor() __asm__ __volatile__("rep; nop")
+#endif
+#endif
+
 #if (defined(_WIN32) && !defined(__CYGWIN__))
 #undef atomic_add
 #undef compare_and_swap
 #undef yield_processor
 #define atomic_add(a, b) ::InterlockedExchangeAdd(a, b)
 #define compare_and_swap(a, b, c)  ::InterlockedCompareExchange(a, c, b)
-#define yield_processor() ::YieldProcessor()
+#define yield_processor() YieldProcessor()
 #define HAVE_ATOMIC_OPS 1
 #endif
 
diff -ru open_jtalk-1.07.orig/mecab/src/winmain.h open_jtalk-1.07/mecab/src/winmain.h
--- open_jtalk-1.07.orig/mecab/src/winmain.h	2013-12-11 14:56:23 +0900
+++ open_jtalk-1.07/mecab/src/winmain.h	2014-02-01 17:20:16 +0900
@@ -46,7 +46,7 @@
 /* for Open JTalk
 #if defined(_WIN32) || defined(__CYGWIN__)
 */
-#if defined(_WIN32) && !defined(__CYGWIN__) /* for Open JTalk */
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) /* for Open JTalk */
 
 #include 
 #include 
diff -ru open_jtalk-1.07.orig/mecab-naist-jdic/Makefile.in open_jtalk-1.07/mecab-naist-jdic/Makefile.in
--- open_jtalk-1.07.orig/mecab-naist-jdic/Makefile.in	2013-12-24 23:26:07 +0900
+++ open_jtalk-1.07/mecab-naist-jdic/Makefile.in	2014-02-01 17:20:16 +0900
@@ -349,7 +349,7 @@
 
 
 char.bin matrix.bin sys.dic unk.dic: naist-jdic.csv matrix.def left-id.def rewrite.def pos-id.def right-id.def char.def unk.def feature.def
-	../mecab/src/mecab-dict-index -d . -o . -f EUC-JP -t @MECAB_CHARSET@
+#	../mecab/src/mecab-dict-index -d . -o . -f EUC-JP -t @MECAB_CHARSET@
 
 clean:
 	rm -f char.bin matrix.bin sys.dic unk.dic

このパッチには、4つのファイルの修正が入っています。1つ目と3つ目は、ユニコード関連のコードを回避するための部分です。2番目はmecab-develの投稿で指摘されていた部分ですが、YieldProcessor()に関する修正です。二カ所に分かれていますが、最初のものはヘッダファイルでのマクロの定義がおかしかったので再定義している部分です。次の部分は、YieldProcessorマクロの内容がコンパイラに定義されている関数のときは問題ないのですが、マクロの内容がインラインアセンブラのときに起きる不具合への対策です。4つ目のファイルの修正は、辞書のコンパイルを行わないようにするだけのものです。これがあるとmakeが止まってしまうのでその回避です。辞書はここで生成されないので、open_jtalkのサイトから文字コードにあったものをダウンロードしてくる必要があります。

このパッチを当ててビルドするスクリプトは次のようになります。面倒なので変数を使って書いていますが、charsetに文字コード名、archにmingwのシステム名です。下の例だと32ビット向けに文字コードutf-8のコードが生成されます。インストールされる場所はprefix変数が示しているbinフォルダなどです。下記スクリプトでは上記のパッチを次の名前とし、open_jtalk-1.07_mingw.patchとして記述しています。上記の64ビット向けのopen_jtalk-1.07_x64.patchを持ってきて、2カ所のコメントを外せば64ビット向けのビルドもできます。

#!/usr/bin/env bash
charset=UTF_8
arch=i686-w64-mingw32
#arch=x86_64-w64-mingw32
export CC="$arch-gcc -static"
host="--host=$arch"
prefix="--prefix=/usr/$arch"
hpath="--with-hts-engine-header-path=/usr/$arch/include"
lpath="--with-hts-engine-library-path=/usr/$arch/lib"
rm -r hts_engine_API-1.08
tar zxvf hts_engine_API-1.08.tar.gz
cd hts_engine_API-1.08
./configure $host $prefix
make
make install
cd ..
rm -r open_jtalk-1.07
tar zxvf open_jtalk-1.07.tar.gz
patch -p0<open_jtalk-1.07_mingw.patch
#patch -p0<open_jtalk-1.07_x64.patch
cd open_jtalk-1.07
./configure $host $prefix $hpath $lpath --with-charset=$charset
make
make install

2つのmake installの先頭に「sudo 」を付ければ、Mingw-w64をインストールしたUbuntuでも使えます。



posted by takayan at 23:07 | Comment(0) | TrackBack(0) | 音声合成 | このブログの読者になる | 更新情報をチェックする

2017年11月13日

OpenJTalkの共有ライブラリを作ってみました。

お久しぶりです。

ずっと書いてませんでした。その間、もうだいぶ経ちますが、熊本地震で家が半壊になったりしてました。

最近、また文章を書きたくなったので、投稿を再開します。

ご挨拶は、これくらいにして、さて本題です。

OpenJTalkの音声をいろんなプログラミング言語から便利に使える、共有ライブラリを作ってみました。名前はとりあえず、jtalkDLLです。Windows、Ubuntu、macOS で動作します。 以前からlinuxのスクリーンリーダー用に非同期発声対応の日本語音声合成APIを作りたかったというのが切っ掛けでした。そちらはまだ完成してないのですが、途中から各言語のFFIに対応させるのが面白くて、そちらに偏ってきてしまったという感じです。

githubに公開しています。

https://github.com/rosmarinus/jtalkdll

README.md に詳しい説明を書いているので、それを読めばインストールできるでしょう。でも、ちょっと細かく書きすぎて読む方はうんざりするかもしれません。

Windows 版だけ、Releaseページにビルド済みファイルを置いてあります。ビルドも環境を構築すれば、build.batのダブルクリックでうまくいくはずです。

他のプラットフォームでは必要なコマンドをそろえたあとで、次のコマンドでインストールしてください。

git clone https://github.com/rosmarinus/jtalkdll.git
cd jtalkdll
bash build

ffiフォルダにあるサンプルコードやそれから実行ファイルを作るビルドスクリプトを参考にすれば、いろいろ書けると思います。

https://github.com/rosmarinus/jtalkdll/tree/master/ffi

まだいくつか不具合もあります。その点もREADME.mdに書いてあります。



posted by takayan at 07:56 | Comment(3) | 音声合成 | このブログの読者になる | 更新情報をチェックする
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。