Open JTalkをWindows 11 & Visual Studio 2022用に修正してビルドする (エラー回避)

# はじめに
世の中のOpen JTalkのWindowsビルドの解説記事を見ていると、Visual Studio 2019以前(2017とか2012とか)の解説ばかりでVisual Studio 2022での解説記事が少ない。実際にVisual Studio 2022環境でビルドしてみると、C++ 17以降で削除された``std::binary_function``がソース内に残っておりコンパイル時点でコケる。
そこで、より現代的な環境でもコンパイル可能なようにソースを修正する。また、参考サイトのコメント欄に書かれていた修正事項も改めて記事としてまとめる。

:::note
文中のミスやより良い方法があればコメント欄でお知らせください。
:::

# ファイルをダウンロードする
文末のサイトを参考に

- `hts_engine_API-1.10.tar.gz`
- `open_jtalk-1.11.tar.gz`

の二つをダウンロードする。他の多数の記事でも解説されているので割愛

# ファイルを展開する

- `hts_engine_API-1.10.tar.gz`を展開する
- `open_jtalk-1.11.tar.gz`を展開する

Windows 11ではデフォルトでgzipが展開できるようになったので楽

`open_jtalk_dic_*`のファイルはダウンロードしなくてもよい
(本記事のMakefileの編集でビルド時に同様の内容が生成される)

# 次の通り配置する
```cmd
C:.
└─open_jtalk-1.11
    ├─bin
    ├─config
    ├─hts_engine_API-1.10
    │  ├─bin
    │  ├─config
    │  ├─include
    │  └─lib
    ├─jpcommon
    ├─mecab
    │  └─src
    ├─mecab-naist-jdic
    ├─mecab2njd
    ├─njd
    ├─njd2jpcommon
    ├─njd_set_accent_phrase
    ├─njd_set_accent_type
    ├─njd_set_digit
    ├─njd_set_long_vowel
    ├─njd_set_pronunciation
    ├─njd_set_unvoiced_vowel
    └─text2mecab
```

# コンパイル環境を準備する
以下のパスがPathに設定されている事
```cmd
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\
```
MSVCの後のバージョンは環境によって少し異なるかもしれない。

反映後、コマンドプロンプトで`cl.exe`や`nmake.exe`が反応する事を書くにしておく

```cmd
> where.exe cl
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\cl.exe
```

```cmd
> cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.43.34810 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]
```

```cmd
> where.exe nmake
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe
```

```cmd
> nmake

Microsoft (R) Program Maintenance Utility Version 14.43.34810.0
Copyright (C) Microsoft Corporation.  All rights reserved.

NMAKE : fatal error U1064: MAKEFILE not found and no target specified
Stop.
```

環境変数のセットアップ

```cmd
>"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
```

# hts_engine_APIをビルドする
```cmd
cd open_jtalk-1.11\hts_engine_API-1.10
nmake /f Makefile.mak
nmake /f Makefile.mak install
```

`C:\`にhts_engine_APIフォルダが作成されるが、**移動しないこと！**
(移動するとOpen JTalkのコンパイルがコケる。Open JTalkもコンパイルしたら移動してOK)

# open_jtalkのソースを修正する
- cpp17で削除された``std::binary_function``を新しい書き方に書き換える
  C:\Users\ユーザー名\Downloads\OpenJTalk\open_jtalk-1.11\mecab\src\dictionary.cpp
  ```cpp
  // 修正前
  template <typename T1, typename T2>
  struct pair_1st_cmp: public std::binary_function<bool, T1, T2> {
    bool operator()(const std::pair<T1, T2> &x1,
                  const std::pair<T1, T2> &x2)  {
      return x1.first < x2.first;
    }
  };
  ```

  ```cpp
  // 修正後
  template <typename T1, typename T2>
  struct pair_1st_cmp {
    bool operator()(const std::pair<T1, T2> &x1,
                    const std::pair<T1, T2> &x2) const {
      return x1.first < x2.first;
    }
  };
  ```
- mecab-naist-jdicの``Makefile.mak``のターゲットを書き換える
  ```Makefile
  # 修正前
  char.bin matrix.bin sys.dic unk.dic: naist-jdic.csv matrix.def left-id.def pos-id.def rewrite.def right-id.def char.def unk.def feature.def ..\mecab\src\mecab-dict-index.exe -d . -o . -f UTF-8 -t sjis
  ```

  ```Makefile
  # 修正後
  char.bin matrix.bin sys.dic unk.dic: naist-jdic.csv matrix.def _left-id.def _pos-id.def _rewrite.def _right-id.def char.def unk.def feature.def ..\mecab\src\mecab-dict-index.exe -d . -o . -f UTF-8 -t sjis
  ```
- open_jtalkの``Makefile.mak``のinstallのターゲットを書き換える
  ```Makefile
  # 修正前
  copy left-id.def $(INSTALLDIR)\dic
  copy right-id.def $(INSTALLDIR)\dic
  copy rewrite.def $(INSTALLDIR)\dic
  copy pos-id.def $(INSTALLDIR)\dic
  ```

  ```Makefile
  # 修正後
  copy _left-id.def $(INSTALLDIR)\dic
  copy _right-id.def $(INSTALLDIR)\dic
  copy _rewrite.def $(INSTALLDIR)\dic
  copy _pos-id.def $(INSTALLDIR)\dic
  ```
# Open JTalkをビルドする
```cmd
cd open_jtalk-1.11
nmake /f Makefile.mak
nmake /f Makefile.mak install
```

# `C:\`から出力バイナリを持ってくる
C直下に

- `open_jtalk`
- `hts_engine_API`

の二つのフォルダが作成されているので、任意の場所にまとめて移動する

# 辞書ファイルを配置する

- `open_jtalk`配下の`dic\`を`bin\`に移動する
- `bin\dic\`の中の`_*.def`の`_`を外す(リネーム)

```text
# 変更前
open_jtalk
├─bin
│      open_jtalk.exe
└─dic
        char.bin
        matrix.bin
        sys.dic
        unk.dic
        _left-id.def
        _pos-id.def
        _rewrite.def
        _right-id.def
```

```text
# 変更後
open_jtalk
└─bin
    │  input.txt
    │  open_jtalk.exe
    └─dic
            char.bin
            left-id.def
            matrix.bin
            pos-id.def
            rewrite.def
            right-id.def
            sys.dic
            unk.dic
```

# ボイスデータを配置する

`open_jtalk\bin`配下に`voices`フォルダを用意し、用意した`.htsvoice`ファイルを配置する

# 実行

```cmd
.\open_jtalk.exe -m .\voices\[ボイスデータ名].htsvoice -x dic -ow output.wav .\input.txt
```

この際、input.txtはShift-JIS形式で保存されている必要がある
(UTF-8だとエラー)

無事に`output.wav`が出力されれば成功
お疲れさまでした

# 参考サイト

https://qiita.com/mkgask/items/0bf9c26dc96e7b0b45ac