Raspberry Pi + MAX98357Aで音を鳴らす ― PipeWireでI²Sオーディオを使う

※この記事は、実際にRaspberry Piを操作しながら行ったChatGPTとのやり取りをもとに、ChatGPTに執筆してもらいました。設定・動作確認はRaspberry Pi 3 Model Bの実機で行っています。また、動作確認用に VOICEVOX で生成した WAV ファイルも以下に置きました(VOICEVOX: ずんだもん)。ご活用下さい。

zundamon.wav

~~~~ ここから本文です ~~~~

Raspberry Piから小型スピーカーを鳴らしたいときに便利なのが、MAX98357A を搭載したI²Sアンプモジュールです。

MAX98357AはI²Sで受け取ったデジタル音声をアナログ信号に変換し、そのままスピーカーを駆動できるClass-Dアンプです。Raspberry Piとは数本の配線だけで接続できるため、小型ロボットなどに音声出力を追加する用途にも向いています。

今回はRaspberry Pi 3 Model BにMAX98357Aを接続し、WAVファイルを再生して音量を変更できるところまで設定してみます。今回のポイントは、後半のPipeWireによる音量管理と再生です。

昔からRaspberry PiやLinuxを触っていると、音声関係では aplayalsamixer.asoundrc あたりを触りたくなるのですが、現在のRaspberry Pi OSではPipeWireが使われています。そこで今回は、

  • ALSAはハードウェアの認識・動作確認に使う
  • 普段の再生や音量管理はPipeWireに任せる

という方針で設定していきます。


動作確認環境

この記事では、次の環境で実際に動作を確認しています。

  • Raspberry Pi 3 Model B
  • Raspberry Pi OS 64-bit
  • Debian GNU/Linux 13.5 (Trixie)
  • Linux kernel 6.18.34+rpt-rpi-v8
  • aarch64
  • PipeWire 1.4.2
  • WirePlumber 0.5.8
  • MAX98357A搭載I²Sアンプモジュール
  • 小型スピーカー

Raspberry Pi OSのオーディオ環境は過去のバージョンから変更されています。

この記事はDebian 13 / Trixie世代のRaspberry Pi OSで動作確認した内容です。古いRaspberry Pi OSでは、PipeWireの有無を含め、設定方法が異なる場合があります。


MAX98357AをRaspberry Piに接続する

今回、MAX98357AとRaspberry Piを次のように接続しました。

MAX98357ARaspberry Pi物理ピン
VIN5V2 または 4
GNDGND6 など
BCLKGPIO1812
LRC / LRCLKGPIO1935
DINGPIO2140

MAX98357Aは I²CではなくI²S で接続します。そのため、i2cdetect を実行してもMAX98357Aは表示されません。


I²Sオーディオを有効にする

現在のRaspberry Pi OSでは、ブート時のハードウェア設定を

/boot/firmware/config.txt

で行います。

今回は、このファイルの最後に次の設定を追加しました。

[all]
dtoverlay=hifiberry-dac

また、Raspberry Pi本体のオンボードオーディオを有効にする次の行はコメントアウトしました。

#dtparam=audio=on

audio のデフォルト値は off なので、今回は明示的に

dtparam=audio=off

とはせず、元の行をコメントアウトしています。

設定が終わったら再起動します。

sudo reboot

ALSAからI²Sオーディオが見えているか確認する

再起動したら、

aplay -l

を実行します。

今回の環境では次のようになりました。

**** List of PLAYBACK Hardware Devices ****
card 0: vc4hdmi [vc4-hdmi], device 0: MAI PCM i2s-hifi-0 [MAI PCM i2s-hifi-0]
card 1: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 [HifiBerry DAC HiFi pcm5102a-hifi-0]

card 1 に、

snd_rpi_hifiberry_dac

が現れています。

ただし、ここでRaspberry Piが「MAX98357AというIC」を検出しているわけではありません。

I²SにはI²Cのようなデバイス検出の仕組みがないためです。

ここで確認できるのは、

Device Tree OverlayによってI²SオーディオデバイスがALSAに登録されている

ということになります。


speaker-testで実際に音を出してみる

次はハードウェアの動作確認です。

今回I²Sオーディオは card 1, device 0 だったので、

speaker-test -D hw:1,0 -c 2 -t sine -f 440

を実行しました。

スピーカーから440Hzのテスト音が聞こえれば、

Raspberry Pi
    ↓
   ALSA
    ↓
   I²S
    ↓
MAX98357A
    ↓
 Speaker

という経路で音を出せていることが確認できます。

停止するときは Ctrl+C です。

なお、card 1 という番号は環境によって変わる可能性があります。自分の環境で aplay -l を実行して確認してください。


音が少し歪む……原因は電源だった

今回の実験では、最初に speaker-test を実行したところ、正弦波なのに少し音が汚く聞こえました。

同時にRaspberry Piの画面には Low Voltage の警告も出ていました。

Raspberry Piの電源状態は、

vcgencmd get_throttled

で確認できます。

今回表示されたのは、

throttled=0x50000

でした。

そこでRaspberry Piの電源ケーブルを交換してみたところ、音がきれいになりました。

MAX98357Aはスピーカーを直接駆動するアンプなので、再生時には当然電力を消費します。

「音は出るけれど、なんとなく歪んでいる」

という場合には、ソフトウェアの設定だけでなく、Raspberry Piへの電源供給やUSBケーブルも疑ってみる価値があります。


さて、音量はどうやって変える?

ここからが今回の記事の本題です。

MAX98357Aには、ALSAから操作できる一般的なハードウェアボリュームがありません。

そのため、

alsamixer

を起動しても、期待していたような音量調整ができませんでした。

昔からRaspberry PiやLinuxを触っていると、

それならALSAの softvol を使えばいいのでは?

と考えたくなります。

実際、ALSAにはソフトウェアで音量を調整する softvol という仕組みがあります。

そこで最初は ~/.asoundrc を作り、

pcm.softvol {
    type softvol
    slave.pcm "hw:1,0"

    control {
        name "SoftMaster"
        card 1
    }
}

pcm.!default {
    type plug
    slave.pcm "softvol"
}

という設定を試しました。

そして、

amixer -c 1 sset SoftMaster 50%

などとすれば、実際に音量を変更できました。

ここまでは問題ありません。

ところが……

Raspberry Piを再起動すると .asoundrc が消えてしまいました。


現在のRaspberry Pi OSではPipeWireが使われている

調べてみると、現在のRaspberry Pi OSでは、オーディオ管理に PipeWire が使われています。

Raspberry Pi OSでは、Bookworm世代から従来のPulseAudioに代わってPipeWireが採用されています。

大雑把に整理すると、現在は、

Application
     ↓
  PipeWire
     ↓
    ALSA
     ↓
Audio Hardware

という構成になっています。

ALSAがなくなったわけではありません。

現在でも、実際のオーディオハードウェアとのやり取りを行う低レイヤーではALSAが重要な役割を担っています。

その上にPipeWireがあり、

  • 複数アプリケーションの音声のミキシング
  • 音量
  • 出力先
  • デフォルトデバイス
  • Bluetoothオーディオ

などを管理します。

つまり、

ハードウェアの確認はALSA、普段の音声管理はPipeWire

と考えると分かりやすそうです。


.asoundrc が消えたのはなぜ?

今回の .asoundrc 消失について調べてみると、現在のRaspberry Pi公式ドキュメントでは、Raspberry Pi OS Desktop環境で ~/.asoundrc を作ることは推奨されていません。

.asoundrc がデスクトップUIから見えるオーディオリソースと干渉する可能性があり、UIによって自動的に削除される場合があるとされています。

したがって、

MAX98357Aに
ハードウェアボリュームがない
        ↓
ALSA softvolを作る
        ↓
.asoundrcを設定する

という方法を取るよりも、今回の環境では、

MAX98357Aに
ハードウェアボリュームがない
        ↓
PipeWire側で
ソフトウェア音量を調整する

方が素直そうです。

もちろん .asoundrc 自体が「古くて使えない」というわけではありません。

PipeWireを使用しない環境や、アプリケーションからALSAへ直接アクセスする必要がある場合には、現在でも利用できます。


PipeWireの状態を確認する

PipeWireの状態は、

wpctl status

で確認できます。

今回の環境では、出力先(Sinks)が次のようになっていました。

Sinks:
    35. Built-in Audio Stereo                 [vol: 0.40]
 *  56. Built-in Audio Digital Stereo (HDMI)  [vol: 0.40]

* が付いているものが現在のデフォルト出力です。

最初はHDMIが選択されていました。

今回MAX98357Aにつながっているのは 35 の方だったので、

wpctl set-default 35

とします。

もう一度、

wpctl status

を実行すると、

Sinks:
 *  35. Built-in Audio Stereo                 [vol: 0.40]
    56. Built-in Audio Digital Stereo (HDMI)  [vol: 0.40]

となりました。

これでMAX98357A側がデフォルトの音声出力になります。

なお、35 というIDは環境によって異なります。

必ず自分の環境で wpctl status を実行して確認してください。


PipeWireで音量を変更する

デフォルトの出力先が決まってしまえば、音量調整はかなり簡単です。

たとえば20%なら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 20%

80%なら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 80%

です。

少しずつ変更することもできます。

5%上げるなら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+

5%下げるなら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-

ミュートのON/OFFなら、

wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle

です。

一度デフォルトの出力先を設定してしまえば、

@DEFAULT_AUDIO_SINK@

に対して操作できるので、アプリケーション側でALSAのカード番号やデバイス番号を意識する必要がありません。


pw-playでWAVファイルを再生する

PipeWireには、音声ファイルを再生するシンプルなコマンドとして pw-play があります。

たとえば、

pw-play sound.wav

これだけです。

デフォルトのSinkとしてMAX98357A側を設定してあるので、出力デバイスを毎回指定する必要もありません。

実際に音量を変えて試してみました。

wpctl set-volume @DEFAULT_AUDIO_SINK@ 20%
pw-play sound.wav

wpctl set-volume @DEFAULT_AUDIO_SINK@ 80%
pw-play sound.wav

ちゃんと20%と80%で音量が変化しました。

これで、

pw-play
   ↓
PipeWire
   ↓
 ALSA
   ↓
 I²S
   ↓
MAX98357A
   ↓
Speaker

という経路で再生できるようになりました。


aplayとpw-playはどう使い分ける?

ここまで試してみると、aplay / speaker-testpw-play の役割も整理できます。

ハードウェアを確認するとき

まず、

aplay -l

でALSAから見えているデバイスを調べます。

そして、

speaker-test -D hw:1,0 -c 2 -t sine -f 440

などと明示的にハードウェアデバイスを指定して音を出してみます。

これは、

I²Sの設定やMAX98357Aまでの音声経路が正しく動いているか?

を切り分けるのに便利です。

普段、音を鳴らすとき

通常の再生では、

pw-play sound.wav

を使います。

出力先はPipeWireに任せます。

音量も、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%

のようにPipeWire側で管理します。

つまり、

ハードウェアの確認
        ↓
       ALSA
aplay / speaker-test


普段の音声再生・管理
        ↓
     PipeWire
   wpctl / pw-play

という使い分けです。


alsamixerに行く前にwpctlを見てみよう

今回MAX98357Aを設定してみて一番面白かったのは、I²Sの配線そのものよりも、Raspberry Pi OSのオーディオ環境が以前とは変わっていることでした。

Linuxのオーディオというと、

aplay
arecord
alsamixer
.asoundrc

あたりを思い浮かべます。

これらが使えなくなったわけではありません。

むしろ、I²Sデバイスの認識確認やトラブルシューティングでは、今でも非常に役立ちます。

一方、現在のRaspberry Pi OSでは、その上にPipeWireがあります。

そのため、

ALSAを使わない

のではなく、

ALSAとPipeWireを役割によって使い分ける

と考えると分かりやすくなります。

特にMAX98357AのようにALSAから調整できるハードウェアボリュームを持たないデバイスでは、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%

で済むPipeWireの音量管理は便利です。

昔からRaspberry Piを使っている人ほど、音量調整で alsamixer に行く前に、

wpctl status

を一度実行してみるとよいかもしれません。


ロボットにも使いやすそう

今回MAX98357Aを使っているのは、Raspberry Piを搭載した小型ロボットで音声を出したかったためです。

PipeWireで音量を管理できることが分かったので、今後ロータリーエンコーダーを取り付ける場合も、

Rotary Encoder
      ↓
     GPIO
      ↓
Volume Controller
      ↓
    wpctl
      ↓
   PipeWire
      ↓
    ALSA
      ↓
     I²S
      ↓
  MAX98357A

という構成にできます。

たとえばエンコーダーを右に回したら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%+

左に回したら、

wpctl set-volume @DEFAULT_AUDIO_SINK@ 2%-

スイッチを押したら、

wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle

といった実装も簡単にできそうです。

アプリケーション側が、

MAX98357AはALSAのcard 1、device 0

といった具体的なハードウェア構成を意識しなくてよいのもメリットです。


まとめ

Raspberry Pi 3 Model BとMAX98357Aを接続し、Raspberry Pi OS(Debian 13 / Trixie)で音声を再生するところまで試してみました。

最終的な構成は、

Application / pw-play
        ↓
     PipeWire
        ↓
       ALSA
        ↓
       I²S
        ↓
    MAX98357A
        ↓
      Speaker

となりました。

今回使った主なコマンドをまとめると、

# ALSAデバイスの確認
aplay -l

# ハードウェアの直接テスト
speaker-test -D hw:1,0 -c 2 -t sine -f 440

# PipeWireの状態確認
wpctl status

# デフォルト出力の設定
wpctl set-default <Sink ID>

# 音量設定
wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%

# WAVファイルの再生
pw-play sound.wav

となります。

最初は alsamixer やALSAの softvol を使う方向で試行錯誤していたのですが、最終的にはPipeWire側で音量とデフォルトデバイスを管理することで、かなりシンプルになりました。

昔からRaspberry Piを使っている人ほど、alsamixer に行く前に一度 wpctl status を実行してみるとよいかもしれません。

なお、PipeWireには再生用の pw-play だけでなく、録音用の pw-record もあります。

マイク入力については、また別の記事で扱いたいと思います。