凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

OpenJTalk の Node.js モジュールを作り直した

はじめに

前回、OpenJTalk を使って Node.js で音声合成するモジュール作った - 凹みTipsで、OpenJTalk で言葉を喋らせることの出来る node モジュールを作りました。が、これを Julius の node モジュールと併用して使おうとしたところ、エラーで動きませんでした。
調べてみましたが、どうやら Julius のモジュールで使用している MeCab と、OpenJTalk で使用している MeCab でのシンボルの衝突が原因のように思われました。
Node.js では C++ モジュール(.node)のロード時は libuv の uv_dlopen を使用して .node を読み込んでおり、uv_dlopen 内では dlopen を RTLD_LAZY でロードしています。

int uv_dlopen(const char* filename, uv_lib_t* lib) {
  dlerror(); /* Reset error status. */
  lib->errmsg = NULL;
  lib->handle = dlopen(filename, RTLD_LAZY);
  return lib->handle ? 0 : uv__dlerror(lib);
}

この読み込み方法がこことかここみたいに以下のように指定できれば良いのかなぁと思ったのですが…。

var mylib = require('mylib', {dlOpenFlags: c.RTLD_LAZY | c.RTLD_GLOBAL});

色々試みましたが無理そうだったので、諦めて OpenJTalk はコンソールから実行する形式にしました。

コード

使い方は前回と同じです。再生は Mac では afplay、linux では aplay で行うようにしています。

追記(2015/01/28)

nocpp ブランチは master ブランチにマージしました。

おわりに

今まで色々と C++ モジュール化しようとしてきましたが、それよりもコンソールから実行できる形式のものは exec で極力処理するようにした方が良いな、と今回の件で強く感じました。C++ モジュール化すると、同じ事を実現するためにより多くのコードを書いて、メンテもして行かなければなりません。
それならば極力実現したいことのコーディングに時間をかけ、JavaScript でどうしても対処できない、とか速度がボトルネックになっている、といった状況のみに C++ モジュール制作を限定するべきだと思います。モジュールを小さなブロックとして考えて、組み合わせて使っていくという Node.js の思想にもあっていますね。