自作で挑む!USB 8chマイクシステムの製作と検証
はじめに
Fairy Devices で ハードウェア/デバイスドライバの開発をしている hikari です。
マルチマイクアレイは、音響信号処理において重要な役割を果たし、スマートスピーカー、ロボット、空間音響など、さまざまな分野で活用されています。
たとえば、音源定位やビームフォーミング、雑音除去といった高度な処理を実現するために不可欠です。
しかし、市販のマルチチャンネルUSBマイクは種類が少なく、入手性やコスト面で課題があります。
「それなら自分で作ってみよう!」と思い立ち、今回はUSB接続の8チャンネルマイクシステムを自作してみました。
構成や制作の工夫、動作確認の内容をまとめつつ、多チャンネルオーディオに取り組むためのベースとなる環境づくりについて紹介していきます。
自作することで、市販品にはない自由なカスタマイズができ、コストを抑えつつ、音響信号処理について深く学ぶことができます。
🎯 目標と構成の概要
自作とはいえ、ある程度使えるマイクにしたいと思います。以下のようなターゲットで作りました。
- Windows PC で認識できる USB Audio デバイス(8chマイク)
- サンプリングレート:48kHz / データ長:16bit
- USB Full Speed(12Mbps)内に収まる帯域構成
- STM32マイコンで音声信号を取り込み、PCへ送信
帯域的には、48kHz × 16bit × 8ch = 約6.1Mbpsなので、USB 2.0 Full Speed(12Mbps)で十分に収まる見込みです。
🔧 使用マイコンボード:NUCLEO-L476RG
STMicroelectronics社のNUCLEO-L476RGというボードが手元にあったので、これを使ってマルチマイクを実現しました。
このボードにはSTM32L476というマイコンが搭載されており、メインCPUは Cortex-M4(80MHz)を使用しています。低消費電力ながら、USBフルスピードデバイスとしても動作可能です。
しかもオーディオ系のペリフェラル(DFSDM、SAI)も搭載されているため、今回の用途に最適でした。
また、USBバスパワーで駆動できるため、外部電源なしで動作可能な点も大きなメリットです。
🎤 マイク:PDM方式を選択
アナログマイクではノイズやインピーダンス調整が厄介なので、PDM(Pulse Density Modulation)方式のデジタルマイクを選びました。
今回使用するのは、秋月電子通商で入手可能なKnowles製のSPH0641LU4Hです。
このマイクは、人の声から超音波(100Hz〜80kHz)まで広くカバー可能な性能を持ち、内部にはΔΣ変調型のADCが内蔵されています。
その結果、ノイズに強く、配線もシンプルで済むのが特徴です。
秋月電子通商で購入可能です。
🤔 PDM信号をどう扱うか? DFSDM vs SAI
STM32L4シリーズには、PDMマイクからの信号を受け取る手段として、DFSDM と SAI の2つの選択肢があります。
DFSDM
DFSDM(Digital Filter for Sigma-Delta Modulators)は、STM32に搭載されているPDM信号処理用のハードウェア機能で、PDMマイクからの信号を直接受け取り、Sincフィルタを通じてデジタルオーディオデータとして扱える点が大きな特徴です。
専用ハードにより、ソフトウェア処理なしに高品質なPDM復調が可能で、分解能やサンプリングレートも柔軟に設定できるため、CPU負荷を抑えつつマイク信号を高精度に扱える点が魅力です。
ただし、実際にマルチチャンネル構成で使ってみるといくつかの課題も見えてきました。
- チャンネルごとの設定が煩雑
- 複数入力のクロック同期が面倒
- ピン数が多く、配線が大変
- DMA設定の調整にも手間がかかる
このように、マルチチャネルになればなるほど構成が複雑化することが分かりました。
SAI
SAI(Serial Audio Interface)は、I2SやTDMといったオーディオ用インターフェースに対応していて、外部のPDM-PCM変換チップと組み合わせることで、マルチチャネル音声信号を一括で取り込むことが可能になります。
🎛️ADAU7002 + SAI によるTDM構成
そこで採用したのが、Analog Devices の ADAU7002 というICです。
ADAU7002
ADAU7002 は、PDM → I2S 変換を行う専用IC で、マイク信号をPCMに変換して出力してくれます。
このICを使うことで、複雑なPDM復調をSTM32にやらせる必要がなくなり、SAI(I2S)でシンプルにデータを受け取るだけの構成が実現できます。
しかも、複数のADAU7002をTDM(時分割多重)で接続することで、最大8chのマイク信号を1本のSAIで受信可能になります。
こちらも秋月電子通商で購入可能です。
TDM(Time Division Multiplexing)
ADAU7002 は I2S出力専用ですが、複数のADAU7002を「デイジーチェーン接続」することでTDM構成が可能です。
以下のように接続します。
- LRCLK(ワードクロック)と BCLK(ビットクロック)を全ADAU7002に共通接続
- 各ADAU7002 のSDATA(データライン)は1本にまとめて順番に信号を出力
- 各マイクの出力タイミングは、内部でスロット制御される(1ch, 2ch, …, 8ch)
この構成を組むことで、最大8chのマイク信号を1本のデータライン(SAI)で取り込むことが可能になります。
STM32はSAIのTDMモードで受信し、DMAを使って効率的に取り込むだけになります。
TDMのタイミングチャート
図:TDMのタイミングチャート
LRCLKはフレームの区切りを示す信号であり、そのクロック周波数が目的とするサンプリングレートに一致している必要があります。
BCLKはビット単位のクロック信号、SDATAは実際の音声データがPDM変調方式で流れる信号です。
各ADAU7002は、LRCLKとBCLKに同期し、自身の担当チャンネルのデータをSDATA上に順番に出力します。
✅ インターフェースはSAI
DFSDMも魅力的ではありましたが、以下の理由からSAI + ADAU7002 構成を最終的に採用しました。
- PDM → PCM変換をICに任せられるため、STM32側の負荷が激減
- TDMで多チャンネルを1ラインにまとめられるため、配線がスッキリ
- SAIはDMAやFIFOも使えるので、リアルタイム転送が容易
- ハードウェア設計・ソフトウェア構成ともにシンプルで安定性が高い
このように、ADAU7002の採用によってシステム全体がスマートで扱いやすい構成になりました。
⚡回路を作ってみよう
🎤マイク周辺
PDMマイク(SPH0641LU4H)を2個と、PDM-I2Sコンバータ(ADAU7002)1つを一組として、
8つのマイクを以下のように結線し、NUCLEO-L476RGボードのSA_SAI_CLK, SA_SAI_FS, SA_SAI_DATの信号線に接続します。
図には書いていないですが、それぞれのADAU7002はconfigピンにスロットの設定をします。また、SPH0641LU4HはL-Rの出力を切り替えるために、SEL信号線はそれぞれGNDとVCCに接続します。
💻USB
NUCLEO-L476RGボードにはUSBコネクタがついていますが、このUSBはデバッグ用として使用します。USBAudioとして動作させるには、別途USBを接続する必要があります。
NUCLEO-L476RGボードからUSB_FS_DPと、USB_FS_DMの信号をUSBコネクタに接続します。
図:Nucleoボードとマイク、USBの接続回路図
図では、電源や、パスコン、データラインのプルダウン抵抗は省略しています。
🔧ソフトウェア開発環境
ソフトウェアの開発には STM32CubeIDE を使用します。使い方の詳細は本記事では扱いませんので、公式ドキュメントや他のチュートリアルをご参照ください。
⚙️STM32 ペリフェラルの設定
STM32L476のハードウェア設定には STM32CubeMX を使用します。
STM32CubeMXは、ペリフェラルの構成やクロック設定などをGUIで行い、初期化コードを自動生成してくれる便利なツールです。
今回は、このツールを使って必要な設定を行っていきます。
💡 注意
名称が少し紛らわしいのですが、ソフトウエアを開発するツールをまとめると
ツール名 | 機能 |
---|---|
STM32CubeIDE | コードの編集・ビルド・デバッグに使用する開発環境 |
STM32CubeMX | レジスタ設定やペリフェラル構成を行い、初期化コードを生成するツール |
このように、目的によって使い分けが必要です。
🕘クロック設定
USB には 48 MHz を供給します。また、SAI には、48 kHz のサンプリングレートを実現するためのクロック設定が必要になります。
SAIで48 kHzのオーディオを処理するために必要な各クロックは以下の通りです。
- LRCLK(フレームクロック):48 kHz
- 1スロットあたりのビット数:32 bit (SAIで設定できるのは16bit or 32bitのみ)
- スロット数:8チャンネル
よって、ビットクロックは、
BCLK = 32 bit × 8 ch × 48 kHz = 12.288 MHz
を設定する必要があります。
また、PDMマイク用のクロックは、
PDMCLK = 48 kHz × 64 = 3.072 MHz
(64倍はADAU7002の内部での逓倍値)
になります。
クロック生成の計算
NUCLEO-L476RGボードは、48 MHzの内蔵クロックを持っており、USBにはこのクロックをそのまま使用できます。
SAIのビットクロック(BCLK)を12.288 MHzに近づけるため、以下のPLL設定が最適です。
48 MHz / 6(PLLM)× 26(PLLN)/ 17(PLLP)= 約12.235 MHz
逆算すると、
12.235 MHz / 32 bit / 8 ch ≒ 47.794 kHz
これは理想の12.288 MHzに対し約0.42%の誤差になります。
この値は設定できるパラメータでは、48 kHzに非常に近く、実用上問題のない範囲と考えられます。
48KHzちょうどに設定するには、外付け外部クロックが必要になるため、ここではこの周波数で妥協することにします。
💡 注意
PLLの分周比(PLLM、PLLN、PLLPなど)の設定可能な値は、使用しているマイコンのハードウェア仕様やクロック源(内部/外部)に依存します。そのため、上記の数値はSTM32L476での一例であり、他のSTM32シリーズでは同じ設定が使えない可能性があります。
クロックの設定
クロックの設定は、STM32 CubeMXを使ってGUIで設定できます。
下図の緑の枠が今回の設定値です。
図:STM32 CubeMXでのクロック設定
PLLの分周比などを設定することで、SAIに必要なクロックを生成します。
🧩SAIの設定(TDMモード)
STM32CubeIDE上での設定例を以下に示します。今回は、SAI A をフリープロトコル・モードのTDM(時分割多重化)で使用し、PDMマイクからの信号を受信しDMAで転送します。
項目 | 設定値 | 説明 |
---|---|---|
Protocol | Free | TDMを使用するためフリープロトコルに設定 |
Audio Mode | Master Receive | クロック(BCLK/LRCLK)を生成しつつ、受信動作 |
Frame Length | 256 bits | スロット数8、スロットサイズ32bit(32×8 = 256bit) |
Data Size | 20 Bits | 有効のデータビット長。PDM→PCM変換後に使用される想定幅(ADAU7002の規定値) |
Slot Size | 32 Bits | 各スロットの幅 |
Number of Slots | 8 | TDMで複数チャンネルを扱えるよう8スロットを定義 |
Audio Frequency | 48 kHz | 目標サンプリングレート |
Real Audio Frequency | 47.794 kHz | 実際のクロック生成値(PLL設定により) |
♾️DMAの設定
PDMマイクからのデータを効率よく受信するために、DMA(Direct Memory Access)を使用してSAIの受信データをメモリに自動転送します。
項目 | 設定値 | 説明 |
---|---|---|
DMA Request | SAI1_A | SAI Aブロックに接続 |
Channel | DMA2 Channel 1 | STM32L476のDMAルーティングに従ったチャンネル設定 |
Direction | Peripheral To Memory | 受信方向。SAIのデータをメモリへ転送 |
Mode | Circular | 循環モード。バッファが満杯になると先頭に戻って再書き込み |
Peripheral Increment | Off | 周辺アドレス(SAIの受信レジスタ)は固定 |
Data Width | Word | 転送単位は32bit(スロットサイズと一致) |
Circularモードを使用することで、常に最新のデータが指定したメモリ領域に上書きされ続け、連続したストリーミング処理が可能になります。
💻USB Audioの設定
USB Audioクラスの実装には、TinyUSBを使用しました。
公式の 4chマイク入力のサンプル をベースに、8chマイク入力に拡張した構成です。
TinyUSBでは、USBデバイスの構成はコード内に直接記述されたコンフィグレーションディスクリプタ構造体によって定義されており、STのCubeMXのようなGUI設定はありません。
設定のポイント
- tusb_config.h と usb_descriptors.c を修正し、インプットターミナルディスクリプタのチャンネル数を8に設定
- フィーチャーユニットディスクリプタに8チャンネル分の設定を記述
- Audioクラスのサブクラス、フォーマットタイプ、エンドポイント構成などを合わせて調整
- CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX を 8 に変更し、マルチチャンネルに対応
- 実際の送信データは、DMAで取得したバッファを使ってUSB経由で送信
📝 補足:TinyUSBはコードベースでUSBディスクリプタを定義するため、自由度は高いものの、記述が煩雑になりがちです。詳細な設定や記述方法については TinyUSBのリファレンスや該当サンプル を参照してください。
📃アプリケーション
SAIはDMAで動作させているので、データが読み込まれるとHAL_SAI_RxCpltCallbackが呼ばれます。
データ長は32bitなので、16ビットに落としてからtud_audio_writeでUSBに書き込みます。
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef hsai)
{
uint16_t usb_buffer[AUDIO_BUFFER_SIZE];
for(i=0; i<AUDIO_BUFFER_SIZE; i++){
usb_buffer[i] = (uint16_t)(audio_buffer[i] & 0xffff);
}
tud_audio_write(usb_buffer, AUDIO_BUFFER_SIZE*2);
}
⭐動かしてみよう!
接続
回路はブレッドボード上に実装しました。SAIを採用したことで、各マイクごとに個別のデータラインを引く必要がなくなり、結線数を大幅に削減することができました。
PCと接続して動作確認を行いました。
写真:完成した8ch USBマイク
録音
Audacityを使ってPC側でのマルチチャンネルの録音をしてみます。
インターフェースをWASAPIに設定し、マイクを今回作製したUSBマイクに。そしてチャンネル数を8chに設定します。
録音ボタンを押すと下の図のように8chに音声が取り込まれます!
一列に並べたマイクの端の方向から発話してたので、チャンネル順に音声の強弱が分かります。
Audacityはこちらから入手できます。
✅まとめ
今回の記事では、マルチチャンネルオーディオの取得に向けた第一歩として、8ch USBマイクの自作について解説しました。市販品では入手が難しい多チャンネル対応のUSBマイクを、比較的安価な部品を用いて実現することを目指した取り組みです。
一般的に多チャンネルのUSBマイクを市販品で揃えるには、数万円以上のコストがかかります。しかし、今回の自作では主要な部品代を一万円以下に抑えながら、8チャンネルのUSBマイクを構築することができました。もちろん、工具や配線材などの付随費用は別途必要ですが、市販品と比べて大幅なコストダウンが可能です。
このように、コスト面で導入をためらっていた多チャンネルオーディオの取得が、より身近なものになる可能性を示せたことは、今後の研究開発や音響制作において大きな意義があると考えています。
今後は、今回作製した8ch USBマイクを活用し、多チャンネル音源を用いた様々な音響処理技術の開発に挑戦していきたいと考えています。
この記事が、同じようにマルチマイクオーディオに興味を持つ方々にとって、自作への第一歩を踏み出すきっかけとなれば幸いです。
※今回使用した部品は比較的入手しやすいものを選びましたが、執筆時点(2025年5月1日)で確認したところ、一部部品の在庫が残りわずかです。もし同様の自作を検討される場合は、最新の在庫状況をご確認ください。
Discussion