Raspberry Pi + MAX98357Aで音を鳴らす ― PipeWireでI²Sオーディオを使う
※この記事は、実際にRaspberry Piを操作しながら行ったChatGPTとのやり取りをもとに、ChatGPTに執筆してもらいました。設定・動作確認はRaspberry Pi 3 Model Bの実機で行っています。また、動作確認用に VOICEVOX で生成した WAV ファイルも以下に置きました(VOICEVOX: ずんだもん)。ご活用下さい。
~~~~ ここから本文です ~~~~
Raspberry Piから小型スピーカーを鳴らしたいときに便利なのが、MAX98357A を搭載したI²Sアンプモジュールです。
MAX98357AはI²Sで受け取ったデジタル音声をアナログ信号に変換し、そのままスピーカーを駆動できるClass-Dアンプです。Raspberry Piとは数本の配線だけで接続できるため、小型ロボットなどに音声出力を追加する用途にも向いています。
今回はRaspberry Pi 3 Model BにMAX98357Aを接続し、WAVファイルを再生して音量を変更できるところまで設定してみます。今回のポイントは、後半のPipeWireによる音量管理と再生です。
昔からRaspberry PiやLinuxを触っていると、音声関係では aplay、alsamixer、.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を次のように接続しました。
| MAX98357A | Raspberry Pi | 物理ピン |
|---|---|---|
| VIN | 5V | 2 または 4 |
| GND | GND | 6 など |
| BCLK | GPIO18 | 12 |
| LRC / LRCLK | GPIO19 | 35 |
| DIN | GPIO21 | 40 |
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-test と pw-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 もあります。
マイク入力については、また別の記事で扱いたいと思います。
