W-SIMをつなげて、発信だけでなく着信も動作するようになってきました。かなりいい加減なSIPスタックで、限定的な状態遷移しかサポートしていないし、エラー処理もロクにしていないので、ときどきおかしくなることがあるのですが、そこそこ遊べるようになってきました。次のネタとしてDTMF音を検出して遊んでみることにします。
世の中には、テレフォンバンキングのように音声ガイダンスにDTMF音で応答することで、メニュー選択ができるサービスがたくさんあります。このようにDTMF音を判別して動作する簡易的なメニューをマイコン上に用意してやれば、X-Lite側からのDTMF入力に応じてマイコンにつながるI/Oを制御したりすることも可能でしょう。音声ガイダンスを用意するのはちょっと大変だし、制御するI/Oを追加製作するのも面倒なので、今あるLCD表示だけを使ってできることを考えようと思います。
こんな構想の第一歩としてDTMF音を検出してみることから始めました。まず最初に通話状態にするのですが、実際にPHS網に電話する必要もないので、発呼処理の開発途中と同じようにマイコン上で呼を終端してダミーのRTPを流すことにします。実際にPHS網へ発呼する動作とマイコン上で終端する場合の区別は電話番号でおこなうことにし、900番台の番号がダイアルされた場合には、マイコン上で終端することとします。
SIPを使う場合にはDTMF信号を送る方式にはいつくかの種類があるようです。
- イン・バンドでの送信 DTMF音を音声信号として送る。
- RFC4733(RFC2833)を使って送信 u-Law音声とは別のRTPペイロードとして、DTMF信号を送信
- SIP INFOを使って送信 SIPのINFOメソッドを使って送信する
X-Liteの説明書によると、X-Liteは上記のすべての方式をサポートしているようですが、設定画面にはこれに係る設定は何もありません。どうやら、相手先のふるまいによって、どの方式を使うかを判断して動作するようです。イン・バンド方式では、音声信号のRTPの中からDTMF成分を検出する作業が必要なのでパス。INFO方式のためにはもう少しSIPスタックをまっとうにした方が良いように思えるので、RTP部分で処理できるRFC4733で行くことにしました。
発呼時にX-Liteが出すINVITEのSDPを調べてみると、
<quote>
m=audio 48684 RTP/AVP 0 101
a=fmtp:101 0-15
a=rtpmap:101 telephone-event/8000
</quote>
というようにRTPのペイロード・タイプとして101をサポートしていることを示しています。いままでは、X-LiteからのINVITEに対してVoIP GWからの応答に含まれるSDPでは
<quote>
m=audio 20002 RTP/AVP 0
a=rtpmap:0 PCMU/8000
</quote>
を返していましたので、DTMFはインバンドで送信されていました。応答SDPを
<quote>
m=audio 20002 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
</quote>
に変更してやったところ、次に示すようにRTP EVENTとしてDTMF信号が出力されるようになりました。
X-Lite上のDTMFボタンを押し続けている間、何度かに分けてRTP EVENTが出力されます。そして、ボタンを離すとendを示すイベントが同じ内容で3回出力されるようです。普通のボタンと同じように、ボタンが押されたことと離されたことの区別もできますから、VoIP GWには何のボタンも付けなくても、電話機のDTMFボタンを代わりに使って操作することができそうですね。