7. USBミニマイクのテストと動作環境の確認

 ALSAやPortAudioを導入したRaspberry Pi Zeroに、「USBミニマイクMI-305」をつないでテストします。このマイクを聴覚補助ツールに使用するつもりはありませんが、今後の音声認識などへの用途を見込んで試すことにしました。Pi Zeroにはイヤフォン出力端子がないので、その対応もやってみます。さらに、ここまでインストールした音声信号処理環境の状態を確認するのも目的です。



1.USBミニマイクとUSB-Audioデバイス


 左はUSBミニマイクの拡大写真です。実際のおよそのサイズは幅20mm、長さ23mm。USB-Aコネクター形式で電源はUSBバスパワーです。
 USBで音声を扱うデバイスのためにUSB Audio Classという規格があり、WindowsやMacなど多くのOSにはAudio Classドライバーが標準で組み込まれています。USBミニマイク MI-305はこの規格に準拠しているので、USBポートに差し込むだけで使用可能になります。
 USB-Audioデバイスは、データが途切れ途切れになるのを防ぐため、一定の転送レートが保証されるアイソクロナス(Isochronous)転送モードで通信しています。
 大まかな信号の流れを把握しておきましょう。録音など入力転送を要求すると、マイクなどのデバイスが取得した音声信号はパケットに変換され、USBを経由してホストに取り込まれます。ホスト側のUSB Audio Classドライバーは、受け取ったパケットから音声データーを取り出してアプリケーションへ渡します。(写真は共立エレショップから)


2.PWMによる音声出力

 Raspberry Pi Zeroには音声出力用の3.5mmジャックがありません。miniHDMIかI2Sを使用できますが、HDMIは今回の目的にはミスマッチ、I2Sはプロジェクトの別の章で検討することになります。ここでは、手っ取り早くGPIOピンから音声信号を取り出すことができればいいので、PWM(Pulse Width Modulation:パルス幅変調)を利用することにしましょう。

 PWMは、パルス幅を変えることで素子に流れる電流の時間を変化させ、ヒーターやモーターを制御する変調方法です。パルスの周期とパルス幅の比率をデューティー比と呼び、次の式で表します。

 このデューティー比を変化させることで制御します。例えばDCモーターに加える電圧を高くすれば早く回転し、低くすれば遅くなります。デジタル制御では出力をHigh(5Vなど)にするかLowにするかといった仕組みが一般的なので、電圧を変化させる代わりに、一定時間内(パルス周期)にどの程度の時間Heighにするか(パルス幅)で回転を調整するわけです。


 これは、パルスというデジタル情報をアナログの運動量に変換しているとも言えます。デューティー比を素早くしかも滑らかに変化させることによって、デジタルの音声信号をアナログ信号に変換することが可能になります。実際にアナログ波形をPWM波形に変換するには、PWM変調器を使って、オーディオ入力信号と基準信号となる三角波とを比較してPWM信号を作成しています。これによって、オーディオ入力信号の振幅がPWM信号のパルス幅に反映されます。

 Raspberry Pi Zeroでは、PWMのパルスを出力する特定のGPIOピンを利用して、音声信号を含むこれらの情報を取り出すことができます。このテーマについてはすでに多くの情報が公開されていますが、Adafruitの『Pi Zero PWM Audio』を参考にしました。そこで説明されている方法よりさらに簡単に利用することができます。

 Raspberry Pi Zeroには、GPIO(General Purpose Input/Output )用に40本のピンヘッダーが付いています。これらのピンに割り当てる機能を、代替機能(Alternate Function)で変更することができます。代替機能にはALT0~5の6種類があり、それぞれのGPIOピンとの関係は、Raspberry Pi Shopさんの『Raspberry PiのGOIPピンと機能』が大変わかりやすく便利なので参考にしてください。
①現在のGPIOピンの機能を確認する

 Poderosa(SSHターミナルエミュレーター)を立ち上げてRaspberry Pi Zeroに接続し、「gpio readall」と入力します。次のようにGPIOピンに割り当てられた機能が表示されます。
 表は左右対称になっていて、BCM欄がGPIOピン番号、Mode欄に機能が表示されています。

②GPIOピンにPWM機能を割り当てる

 いろいろなピンの指定が考えられますが、ここでは左右のPWM出力用として、GPIO18とGPIO13に割り付けることにします
    PWM0 : GPIO18ピン ..... ALT5で割り当て
    PWM1 : GPIO13ピン ..... ALT0で割り当て
 ALTの割り付けにはgpioコマンドを使用し、次のように入力します。
$ gpio -g mode 18 ALT5
$ gpio -g mode 13 ALT0


③変更結果の確認

 先ほどと同様にして、変更後のGPIOピンの状態を表示してみましょう。
 これで変更されていることが確認できました。
 gpioで設定した内容はリブートでリセットされるので、再起動時に自動実行するように設定する必要があります。今回は一時的なテストが目的なので、リブート時には再度指定しなおすことにします。


3.USBミニマイクを組み付ける

①USB変換ケーブル

   

 USBミニマイクはUSB-Aコネクターなので、Raspberry Pi ZeroのmicroUSBポートへセットするために変換器が必要になります。左図はUSB-microUSB変換ケーブル(ZUH-OTG01)で、500円前後で入手することができます。


②ヘッドフォンアンプの改造

   

 本シリーズの第4章『4.アナログ聴力補助ツールの製作』において、ヘッドフォンアンプを高感度マイクアンプキットと接続するために、アンプ基板の裏面に線材をハンダ付けしました。今後は音声信号プロセッサーであるRaspberry Pi ZeroのGPIOピンと接続するため、その線材を取り除いて、代わりにGPIOピンに差し込むことができるメスプラグの付いたジャンパーワイヤーをハンダ付けします。「20cm ジャンパーワイヤ(メス-オス)40本セット」がamazonなどで300円前後で入手できます。


③全体を結線する

 Raspberry Pi Zeroの電源を切ります。ヘッドフォンアンプのGNDをPi ZeroのGNDへ、左右のジャンパーワイヤーをそれぞれGPIO18とGPIO13に接続します。PWMをアナログ変換するには、ヘッドフォンアンプとの間に抵抗器とコンデンサーで構成したローパスフィルターを設置すべきなのですが、ブレッドボード上でやってみると(Raspberry Pi 3などのイヤフォンジャック出力回路と同じ100Ωと100μFで)音がこもってしまいます。そのためここではとりあえず直結しています。次にUSBミニマイクを挿したUSB-microUSB変換ケーブルをPi ZeroのUSBポートへ差し込みます。完了したらPi Zeroの電源を入れます。
   


4.音声信号処理環境の確認

 USBミニマイクを取り付けると、ALSAがその変化を感知して音声信号処理環境を整えます。音出しをする前にこれらの状態を確認しておきましょう。
①接続状態の確認

 まず、サウンドカードの認識状況を確認します。
$ cat /proc/asound/cards 0 [ALSA ]: bcm2835_alsa - bcm2835 ALSA bcm2835 ALSA 1 [Device ]: USB-Audio - USB PnP Sound Device C-Media Electronics Inc. USB PnP Sound Device at usb-20980000.usb-1, full speed
 snd_bcm2835は内蔵オーディオモジュールです。USBマイクが認識されていることがわかります。


②サウンドカードの優先度

$ cat /proc/asound/modules 0 snd_bcm2835 1 snd_usb_audio
 内蔵オーディオモジュールsnd_bcm2835が最優先されていて、次にUSBマイクが続きます。


③サウンドデバイスの確認

$ cat /proc/asound/devices 0: [ 0] : control 16: [ 0- 0]: digital audio playback 17: [ 0- 1]: digital audio playback 18: [ 0- 2]: digital audio playback 32: [ 1] : control 33: : timer 56: [ 1- 0]: digital audio capture
 playbackは再生デバイスです。最終行にマイクデバイスcaptureが認識されていることがわかります。


④PCMデバイスの状態

$ cat /proc/asound/pcm 00-00: bcm2835 ALSA : bcm2835 ALSA : playback 7 00-01: bcm2835 IEC958/HDMI : bcm2835 IEC958/HDMI : playback 1 00-02: bcm2835 IEC958/HDMI1 : bcm2835 IEC958/HDMI1 : playback 1 01-00: USB Audio : USB Audio : capture 1
 PCMデバイスとしてUSB Audioのマイクが認識されています。


⑤スピーカー(イヤフォン)の設定確認

$ amixer -c 0 contents numid=3,iface=MIXER,name='PCM Playback Route' ; type=INTEGER,access=rw------,values=1,min=0,max=3,step=0 : values=0 numid=2,iface=MIXER,name='PCM Playback Switch' ; type=BOOLEAN,access=rw------,values=1 : values=on numid=1,iface=MIXER,name='PCM Playback Volume' ; type=INTEGER,access=rw---R--,values=1,min=-10239,max=400,step=0 : values=-2000 | dBscale-min=-102.39dB,step=0.01dB,mute=1 numid=5,iface=PCM,name='IEC958 Playback Con Mask' ; type=IEC958,access=r-------,values=1 : values=[AES0=0x02 AES1=0x00 AES2=0x00 AES3=0x00] numid=4,iface=PCM,name='IEC958 Playback Default' ; type=IEC958,access=rw------,values=1 : values=[AES0=0x00 AES1=0x00 AES2=0x00 AES3=0x00]
 numid=3がvalues=1になっていることから、アナログオーディオが有効になっている状態がわかります。


⑥再生デバイスの確認

$ aplay -l **** ハードウェアデバイス PLAYBACK のリスト **** カード 0: ALSA [bcm2835 ALSA], デバイス 0: bcm2835 ALSA [bcm2835 ALSA] サブデバイス: 7/7 サブデバイス #0: subdevice #0 サブデバイス #1: subdevice #1 サブデバイス #2: subdevice #2 サブデバイス #3: subdevice #3 サブデバイス #4: subdevice #4 サブデバイス #5: subdevice #5 サブデバイス #6: subdevice #6 カード 0: ALSA [bcm2835 ALSA], デバイス 1: bcm2835 IEC958/HDMI [bcm2835 IEC958/HDMI] サブデバイス: 1/1 サブデバイス #0: subdevice #0 カード 0: ALSA [bcm2835 ALSA], デバイス 2: bcm2835 IEC958/HDMI1 [bcm2835 IEC958/HDMI1] サブデバイス: 1/1 サブデバイス #0: subdevice #0
 全てのサウンドカードとオーディオデバイスを表示しています。


⑦録音デバイスの確認

$ arecord -l **** ハードウェアデバイス CAPTURE のリスト **** カード 1: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio] サブデバイス: 1/1 サブデバイス #0: subdevice #0
 すべての録音デバイスを表示しています。


5.USBミニマイクのテストと評価

 音出しのテストを始めます。ヘッドフォンアンプにイヤフォンを接続し、アンプのボリュームを絞ってください。
①音量を調整する

 ALSAが保持している音量をセットしなければ音が小さすぎて聞こえません。そこで、alsamixerで音量を設定します。以前にも述べたように、poderosaで操作すると画面が乱れるので、WindowsリモートデスクトップでRaspberry Pi Zeroに接続してLXTerminalを起動します。LXTerminalで「alsamixer」と入力すると下図のようなミキサー画面が表示されます。

 初期値は「再生」の音量調整画面です。スケールがゼロになっているので[↑]キーでレベル値が85になるまで上げます。上がりすぎたら[↓]で下げることができます。設定ができたら[ESC]キーで終了します。もう一度「alsamixer」を入力して立ち上げ、今度は[F6]キーでサウンドカード選択画面を表示させます。表示項目から[USB PnP Sound Device]を選択して[Enter]キーを押下します。続いて[F4]キーを押すと「録音」音量調整画面に切り替わるので、再生と同様にしてレベル値を87あたりまで上げて[ESC]キーで終了します。 音量の設定が終わればLXterminalは閉じてかまいません。


②音声を再生してみる

 次のコマンドを入力してください。アンプの左右のボリュームを少しずつ右に回して、「Front center」の音声がちょうど良い大きさで聞こえるように調整します。ほんのわずか(角度で数度以内)上げたところで明瞭に聞こえるはずです。
$ aplay /usr/share/sounds/alsa/Front_Center.wav


③マイクの音を再生する

 いよいよマイクからの音声を聞いてみましょう。arecordコマンドを下記のように入力すると、マイクの音をイヤフォンに再生し続ける状態になります。
$ arecord -f S16_LE -r 44100 -D hw:1 | aplay 録音中 WAVE 'stdin' : Signed 16 bit Little Endian, レート 44100 Hz, モノラル 再生中 WAVE 'stdin' : Signed 16 bit Little Endian, レート 44100 Hz, モノラル

 最初は何も聞こえないと思います。マイクの近くで発声しながら、ドライバーでヘッドフォンアンプの半固定ボリュームを音が聞こえるまでゆっくり右に回します。時計の位置で12時あたりになると十分な音量になるはずです。しかし、1秒程度の遅延が発生してエコーがかかったように聞こえるのは妙な感じです。
 テレビのスイッチを入れてマイクを近づけてみましょう。どうも音が小さくて聞こえにくいですね。さらにボリュームを右に回すと聞こえるようになりましたが、ブ~ンというノイズが耳につきます。
 全体的な評価としては、
  ・1~2m程度の範囲の音は拾いやすいが、それ以上離れると聞き取りにくい。
  ・内容は明瞭に把握できるが、高音と低音がカットされている感じ。
  ・テレビの音をはっきり聞き取ろうとボリュームを上げたら、ノイズが大きくなって内容がかき消される感じ。
  ・1秒程度の遅延はどうも気持ち悪い。
といったところでしょうか。
 けれども、音声認識用のマイクとしては十分使えそうな感触です。

<危険・注意!>
 この状態で先の「Front center」を発声させてはいけません。また、WAVEファイルなどの再生も厳禁です。強烈な音量で耳を傷めます! もう一度ボリュームを絞り込んでください。


6.PortAudioサンプルプログラムのテスト

 最後に、前回インストールしたPortAudioのサンプルプログラムを実行してみましょう。まずはその時実行したpa_devs.cを、改めてコンパイルして実行させます。それぞれの「機能」は以下の通りで、「コンパイル」の記述にしたがってコンパイルし、「実行」の要領で実行してください。
 まず、次のようにPortAudioのexampleフォルダーに移動します。

$ cd $ cd portaudio/examples

①デバイス情報の表示

 ・機能: デバイス情報など、使用可能なデバイスを一覧表示します。
 ・コンパイル: gcc pa_devs.c -lportaudio
 ・実行: ./a.out
実行結果
 以下の内容が表示されます。最初の冗長な部分は省略しています。「device #2」に[ Default Input ]としてUSB PnP Sound Deviceが追加されているのがわかります。
Number of devices = 4 --------------------------------------- device #0 [ Default Output ] Name = bcm2835 ALSA: IEC958/HDMI (hw:0,1) Host API = ALSA Max inputs = 0, Max outputs = 8 Default low input latency = -1.0000 Default low output latency = 0.0016 Default high input latency = -1.0000 Default high output latency = 0.0348 Default sample rate = 44100.00 Supported standard sample rates for half-duplex 16 bit 8 channel output = 44100.00, 48000.00, 88200.00, 96000.00, 192000.00 --------------------------------------- device #1 Name = bcm2835 ALSA: IEC958/HDMI1 (hw:0,2) Host API = ALSA Max inputs = 0, Max outputs = 8 Default low input latency = -1.0000 Default low output latency = 0.0016 Default high input latency = -1.0000 Default high output latency = 0.0348 Default sample rate = 44100.00 Supported standard sample rates for half-duplex 16 bit 8 channel output = 44100.00, 48000.00, 88200.00, 96000.00, 192000.00 --------------------------------------- device #2 [ Default Input ] Name = USB PnP Sound Device: Audio (hw:1,0) Host API = ALSA Max inputs = 1, Max outputs = 0 Default low input latency = 0.0087 Default low output latency = -1.0000 Default high input latency = 0.0348 Default high output latency = -1.0000 Default sample rate = 44100.00 Supported standard sample rates for half-duplex 16 bit 1 channel input = 44100.00, 48000.00 --------------------------------------- device #3 Name = dmix Host API = ALSA Max inputs = 0, Max outputs = 2 Default low input latency = -1.0000 Default low output latency = 0.0213 Default high input latency = -1.0000 Default high output latency = 0.0213 Default sample rate = 48000.00 Supported standard sample rates for half-duplex 16 bit 2 channel output = 48000.00 ----------------------------------------------


 == 以下の再生テストの前に、音量を小さく絞っているか再確認してください! ==


②ノコギリ波の再生

 ・機能: 単純なノコギリ波を再生します。
 ・コンパイル: gcc paex_saw.c -lportaudio
 ・実行: ./a.out
実行結果
 左右のイヤフォンから音程が異なるノコギリ波が再生されます。


③正弦波の再生

 ・機能: 正弦波を再生します。
 ・コンパイル: gcc paex_sine.c -lportaudio -lm
 ・実行: ./a.out
実行結果
 左右のイヤフォンから、音程の異なるサイン波が5秒間再生されます。


 以上でPortAudioのCプログラムをコンパイルして実行させることができました。これらの音をイヤフォンから聞くことで、音声信号処理の世界がより身近になったことと思います。

 USBミニマイクによる実験はここまでです。PWMによる音声データのハンドリング、ALSAの働きや音声信号処理環境が保持している情報の一部などを垣間見ることができました。
 次回はデジタルマイクによる実験の準備としてI2Sについて考え、必要なソフトウェアモジュールのセットアップを行います。お楽しみに!