PocketSphinxのPythonパッケージの扱いに苦戦した話

# PocketSphinxとは
PocketSphinxは連続音声認識を行う音声認識エンジンです。
英語しか対応していないので、日本語には向かないようです。
（**強引に対応させる手があるようですが、話が脱線するので割愛します。。。**）

# 実行環境
今回は以下の環境で動作確認を行いました。

- Windows10
  - Anaconda(Python 3.7.9)

# パッケージインストール
`pip install pocketsphinx`で終わり、とはならないです。。。
PocketSphinxをインストールするには、swigとBuild Tool(C++)が必要になります。

swigは[こちら](http://rinatz.github.io/swigdoc/install.html)を参考にインストールできました。
Build Toolは[こちら](https://visualstudio.microsoft.com/ja/thank-you-downloading-visual-studio/?sku=BuildTools)からダウンロードできます。

準備ができたら、pipでPocketSphinxをインストールします。

```
pip install pocketsphinx
```

# サンプルコード実行
PocketSphinxのサンプルコードは以下のようになっています。
この通り実行すると、英単語を検知してくれます。

```python:sample.py
import os
from pocketsphinx import LiveSpeech, get_model_path

model_path = get_model_path()

speech = LiveSpeech(
    verbose=False,
    sampling_rate=16000,
    buffer_size=2048,
    no_search=False,
    full_utt=False,
    hmm=os.path.join(model_path, 'en-us'),
    lm=os.path.join(model_path, 'en-us.lm.bin'),
    dic=os.path.join(model_path, 'cmudict-en-us.dict')
)

for phrase in speech:
    print(phrase)
```

LiveSpeechのデフォルト値は以下のようになっているそうです。

```
verbose = False
logfn = /dev/null or nul
audio_file = site-packages/pocketsphinx/data/goforward.raw
audio_device = None
sampling_rate = 16000
buffer_size = 2048
no_search = False
full_utt = False
hmm = site-packages/pocketsphinx/model/en-us
lm = site-packages/pocketsphinx/model/en-us.lm.bin
dict = site-packages/pocketsphinx/model/cmudict-en-us.dict
```

# 参照先ディレクトリの理解
PocketSphinxでは、このようなエラーが出る事象が発生しました。
この事象の原因を整理していきます。

```
RuntimeError: new_Decoder returned -1
```


hmm / lm / dictで使用している`model_path`は以下のように設定しています。

```
model_path = get_model_path()
```

このパスをprintしてみるとこのようになります。

```
C:\Users\<UserName>\.conda\envs\pocketsphinx\lib\site-packages\pocketsphinx\model
```

```
(pocketsphinx) C:\Users\<UserName>\.conda\envs\pocketsphinx\Lib\site-packages\pocketsphinx\model>tree /f
C:.
│  cmudict-en-us.dict
│  en-us.lm.bin
│
└─en-us
        feat.params
        mdef
        means
        noisedict
        README
        sendump
        transition_matrices
        variances
```

どうやら、pipでインストールしたパッケージの中にデフォルトの辞書データ諸々が含まれているようです。
このパスが間違っていると`RuntimeError`が発生するようです。

> 余談
> このエラーの話は検索すると情報があるのですが、わざわざen-usをダウンロードするように書かれていたり、
> そもそも、エラーが回避できていないコードがあったりしました。
> （極めつけは、そもそもPythonとして、パスの置換に失敗しているコードも出てきました。。。）
> 当初、自分もパスの確認を怠ったのもあり、ますます謎が深くなった事象でした。

# 自作辞書データの適用
今回はこのようなディレクトリ構成になっています。
`model\sample.dict`が自作辞書データです。

```
(pocketsphinx) C:\Users\<UserName>\Documents\pocketsphinx_sample>tree /f
C:.
│  exmaple.py
└─model
       sample.dict
```

次に、LiveSpeechの引数を見ると、以下の引数を設定すればよさそうです。
lmについては、`False`を設定する方法もドキュメントに記載されていますが、何故かRuntimeErrorになるので、対象としています。

```
hmm=os.path.join(model_path, 'en-us'),
lm=os.path.join(model_path, 'en-us.lm.bin'),
dic=os.path.join(model_path, 'cmudict-en-us.dict')
```

```python:exmaple.py
import os
from pocketsphinx import LiveSpeech, get_model_path

model_path = get_model_path()
my_model_path = 'C:\\Users\\<UserName>\\Documents\\pocketsphinx_sample\\model'

speech = LiveSpeech(
    hmm=os.path.join(model_path, 'en-us'),
    lm=os.path.join(model_path, 'en-us.lm.bin'),
    dic=os.path.join(my_model_path, 'sample.dict'),
)

for phrase in speech:
    print(phrase)
```

# 残った疑問点
自分の目的としては辞書データを読み込んでくれればよいので、これで目的は達成できました。
しかし、`lm=False`でエラーになる原因が不明な状態なままです。
また、gram（文法ファイル）を読み込ませる`jsgf`という引数を書いているサンプルコードも見られましたが、
PocketSphinxのGithubでコードを確認しても、そのような引数はなさそうでした。
文法ファイルの読み込み方も今後必要になれば確認が必要です。

# 参考
http://rinatz.github.io/swigdoc/install.html
https://pypi.org/project/pocketsphinx/
https://visualstudio.microsoft.com/ja/thank-you-downloading-visual-studio/?sku=BuildTools
https://stackoverflow.com/questions/44339312/new-decoder-returned-1-when-trying-to-run-pocketsphinx-on-raspberry-pi/51346264#51346264