Phonetic Trainer for Radio Operator

# Abstract
This article describes how to make a phonetic trainer for the Radio Operator with the NanoPi-NEO.

Having The NanoPi-NEO a header for USB onboard, so connecting and set-up for USB-DAC is very easy.

# はじめに
先日日本無線協会のWebページを見ていたら、特殊無線技士の国家試験の案内が出てました。どれどれ、日程は....

どうやら航空特殊無線技士の試験が10月23日に行われるようです。ちょうど公休日だし、陸上(第二級陸上無線技術士)と海上(第四級海上無線通信士)は持ってるけど「空」はまだだったよな。申し込んでこようっと!!

というわけで受験を申し込んだ後で試験科目を確認する(先に確認しろ)と「電気通信術」がある。調べるとフォネティックコードで読み上げられる電報を書き取ったり、電報を読み上げたりするらしい。練習が必要だけどさてどうやって練習したものか....。読み上げはいいとして書き取りが問題だ。

情報通信振興会が出してるCDで練習するのが定番だけど、CDだとスピード変えられないしなぁ。どうしたものか。

そうだ!! ちょうど手元にポンチャックマシーン化途上のNanoPi-NEOがある!! こいつにフォネティックをしゃべらせよう!!

というわけで今回はNanoPi-NEOでフォネティックをしゃべらせる作戦です。

# 無線従事者国家試験 電気通信術(受話)実施要項

次の資格の試験で電気通信術(受話)があります。

1. 総合無線通信士(第一級及び第二級)
2. 海上無線通信士(第一級～第三級)
3. 航空無線通信士
4. 第一級海上特殊無線技士
5. 航空特殊無線技士

なお、第三級総合無線通信士(古の漁船級無線通信士)、及び第四級海上無線通信士(古の電話級無線通信士)には受話の試験はありません。

試験のやり方はいずれも同じで、試験監督のおっちゃんがラジカセをもってきます(以前はカセットテープだったそうですがこないだ受けに行ったらCDに進化していたwwww)。書き取り用紙が配布されるので資格名と受験番号と名前を書き、テストの音声が流されるので聞き取りにくい人は申し出ましょう。席の移動など配慮してくれます。

テスト用の電報が流れたあと本番の電報が流れてきます。書き取るのは本番の電報のほうです。注意しましょう。

「はじめます 本文 Alpha Bravo Charlie.....終わり」

こんな感じです。なお、1分間50文字で欧文の暗文(5文字区切り)が約2分間流れてきます。

こいつをもとのアルファベットに直してがしがし書き取ればOKです。電報終了後5秒で試験終わりです。

注意事項ですが、50文字/分は遅いようで結構忙しいです。訂正の余裕はありません。訂正および脱字は-1点ですが、誤字は-3点と結構ダメージがでかいので、怪しいと思ったときは空白(脱字)にしておくのがよいです。

# 作り方
## 用意するもの

1. NanoPi-NEO
2. USB-DACのIC。CMedia社のCM102を使いました。スピーカ鳴らせるし。
3. 若干の電子部品
4. 情報通信振興会が出してる欧文電報送信練習帳

なお、欧文電報送信練習帳は本屋では売っていません。情報通信振興会の通信販売で買えます。本番試験で使うのと同じフォーマットの受信用紙もありますので一緒に買っておくのがよいでしょう。私は日本無線協会近畿支部の近くの振興会に直接買いに行きました。振興会のおばちゃん、いつもありがとう。

## 回路

CM102はUSB-DACのICです。PCショップで売られている安物USBスピーカにも使われていたりします。12Mc/sの水晶と若干の抵抗やコンデンサを外付けするだけでスピーカを鳴らすことができます。値段も1個600円程度とお手頃です。

このCM102をNanoPi-NEOのUSB端子に接続します。といってもラズパイのようにUSBケーブルを引き出して接続する必要はありません。NanoPi-NEOの基板上ヘッダにはUSBの信号線が2口分出ているのでそこに接続すればOKです。

回路図は下図の通りです。おうちにCADがないので手描きです。

![DSCF2515.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449377/c7f034cd-4b10-cbe1-313e-5e7f8f1e543f.jpeg)


## プログラムの用意

### espeakのコンパイル

最近ではGoogleさんに頼んでしゃべってもらうこともできるようですが、フォネティックの読み上げごときでGoogleさんのお世話になるのもどうかと思われたので、音声合成のプログラムを用意しました。

音声合成のプログラムには音声の素となるデータを加工して合成するものと、フォルマントをシミュレーションして合成するものがあります。今回はフォルマント合成方式のespeakを使用しました。

ソースファイルを展開してコンパイルします。espeakは直接サウンドデバイスから音声を出すこともできますが、今回はwavファイルのみの生成なので、展開したファイル中のsrc/Makefileを少し編集します。

``` src/Makefile
INSTALL = install
LN_SF = /bin/ln -sf
MKDIR = mkdir -p

# 'runtime' uses pulseaudio if it is running, else uses portaudio
#AUDIO = runtime
#AUDIO = portaudio <- ここをコメントアウトする
#AUDIO = portaudio0
#AUDIO = portaudio2
#AUDIO = pulseaudio
#AUDIO = sada
(以下省略)
```

音声出力に何を使うかを指定するところがあり、デフォルトではPortAudioが指定されているので、指定をすべて外します。

あとは通常通りコンパイルしてインストールするだけです。

### サウンドデバイスの設定

しゃべらせる前にオーディオ再生デバイスの設定が必要です。I2S DACだとカーネルモジュールのインストールだとかOSのパラメータ設定だとか面倒なことがいろいろあったりしますが、USBオーディオデバイスは接続するだけでOSから認識されるのでとっても楽ちんです。

まずは接続したCM102がUSBデバイスとして認識されているか確認します。

```
pi@NanoPi-NEO:~$ lsusb
Bus 008 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 002: ID 0d8c:0103 C-Media Electronics, Inc. CM102-A+/102S+ Audio Controller
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

次に、alsaからUSB-DACのデバイスの番号と名前を調べます。

```
pi@NanoPi-NEO:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Pcm5102a [Pcm5102a], device 0: Playback pcm5102a-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: sndhdmi [sndhdmi], device 0: SUNXI-HDMIAUDIO sndhdmi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 2: Device [USB Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
pi@NanoPi-NEO:~$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
sysdefault:CARD=Pcm5102a
    Pcm5102a,
    Default Audio Device

(途中省略)

hw:CARD=Device,DEV=0
    USB Sound Device, USB Audio
    Direct hardware device without any conversions
plughw:CARD=Device,DEV=0
    USB Sound Device, USB Audio
    Hardware device with all software conversions
```

接続したUSB-DACはCard #2のDevice #0として認識されています。なお、カードやデバイスの番号は実際にはこれと異なることがありますので、必ず確認してください。これを自分のホームディレクトリ直下の.asoundrcファイルに反映させます。

```/home/pi/.asoundrc
pcm.!default {
        type hw
        card 2
        device 0
}

ctl.!default {
        type hw
        card 2
}
```

aplayコマンドで適当なwavファイルを再生して音が出るか確認してください。音が出ない場合は回路をもう一度確認するとともに、設定を確認してください。

### フォネティック変換プログラムを書く

音が出ることが確認できたら次に欧文の文字列をフォネティックコード化するプログラムを書きます。今時の人だったらたぶんPythonだと思いますが、私は昔の人なのでCで書きました。

```phonetic.c
/*
        phonetic.c
        converts ascii text -> phonetic code
        14. Aug., 2019 rev.0.1 by JO3VPS
*/

#include <stdio.h>
#include <ctype.h>

struct phonetic {
        char name;      // character
        char *phonetic_code;    // phonetic code
};

const struct phonetic phonetic_list[]=
{
        { 'A',"ALFA" },
        { 'B',"BRAVO" },
        { 'C',"CHARLIE" },
        { 'D',"DELTA" },
        { 'E',"ECHO" },
        { 'F',"FOXTROT" },
        { 'G',"GOLF" },
        { 'H',"HOTEL" },
        { 'I',"INDIA" },
        { 'J',"JULIETT" },
        { 'K',"KILO" },
        { 'L',"LIMA" },
        { 'M',"MIKE" },
        { 'N',"NOVEMBER" },
        { 'O',"OSCAR" },
        { 'P',"PAPA" },
        { 'Q',"QUEBEC" },
        { 'R',"ROMEO" },
        { 'S',"SIERRA" },
        { 'T',"TANGO" },
        { 'U',"UNIFORM" },
        { 'V',"VICTOR" },
        { 'W',"WHISKEY" },
        { 'X',"XRAY" },
        { 'Y',"YANKEE" },
        { 'Z',"ZULU" },
        { '0',"ZERO" },
        { '1',"ONE" },
        { '2',"TWO" },
        { '3',"THREE" },
        { '4',"FOUR" },
        { '5',"FIVE" },
        { '6',"SIX" },
        { '7',"SEVEN" },
        { '8',"EIGHT" },
        { '9',"NINE" },
        { '.',"DECIMAL" },
        { ' ',"\n\n" },
        { '\n',"\n\n" }
};

int main(int argc, void *argv)
{
        int i,j;
        char k;
        while(!feof(stdin))
        {
                k = toupper(getchar());
                for(i=0;i<(sizeof(phonetic_list)/sizeof(struct phonetic));i++)
                {
                        if(phonetic_list[i].name==k)
                        {
                                printf("%s  ",phonetic_list[i].phonetic_code);
                        }
                }
        }
}
```

コンパイルしたら実行用のシェルスクリプトを書きます。

```phonetic.sh
#!/bin/bash
sleep 5
echo "honbun" | espeak -s 100 --stdout | aplay -D plughw:2
sleep 1
time cat $1 | ./phonetic | espeak -s $2 -g 5 --stdout | aplay -D plughw:2
sleep 1
echo "owari" | espeak -s 100 --stdout | aplay -D plughw:2
```

aplayの"-D"オプションはなくても音は出るはずです。

# しゃべってもらおうじゃないか

しゃべらせるための原稿を書きます。無線従事者の国家試験の電気通信術(受話)では欧文の暗文が5文字間隔で流れてくるのを書き取ります。大体こんな感じです。(例文は欧文電報送信練習帳より)

```
pi@NanoPi-NEO:~/phonetic$ cat 001.txt
seclt cfhom bdigr clakh dlmko fnkoe ebnoh abqjd
hrswx itwve jxyzf lfgmi mhjkw nilmr odfum pkucn
```

なお、フォネティック変換プログラム中で小文字は大文字に変換してますので、原稿は大文字でも小文字でもかまいません。

しゃべらせるには次のようにシェルスクリプトを実行します。2番目のパラメータは読み上げ速度です。実測で約67文字/分ですから、本番より約3割速いです。

```
$ ./phonetic.sh 001.txt 110
```

本番の試験と同じように「本文 Sierra Echo Charlie Lima Tango...おわり」

と流れてくれば成功です。あとはがしがし書き取るべし。