Automatically save the volume of your ReSpeaker 2-Mics Pi HAT

For my Rhasspy voice assistant I use the Seeed ReSpeaker 2-Mics Pi HAT on a Raspberry Pi: it's cheap and has two on-board microphones, so you only need to a add a speaker to use it for voice projects.

The drivers are open source and they can be installed easily from the respeaker/seeed-voicecard repository together with supporting systemd services. However, every time you reboot your Raspberry Pi, the playback volume is set to its maximal value, so the feedback sounds and replies from your voice assistant echo through the whole house.

I never bothered to change this behaviour, but when someone on the Rhasspy forum asked about it yesterday (Rhasspy with respeaker 2 hat starts with highest playback volume) I decided to dive into the details.

It turns out that the seeed-voicecard.service systemd script removes your system's asound.conf and asound.state at each boot, replacing them by its default files.

If you know this and read the /usr/bin/seeed-voicecard shell script, the solution for the state file (containing your volume settings) is simple: let the ALSA service store to and restore from this file installed by the Seeed driver, /etc/voicecard/wm8960_asound.state. Have a look at the alsa-restore.service file:

$ systemctl cat alsa-restore.service
# /lib/systemd/system/alsa-restore.service
#
# Note that two different ALSA card state management schemes exist and they
# can be switched using a file exist check - /etc/alsa/state-daemon.conf .
#

[Unit]
Description=Save/Restore Sound Card State
Documentation=man:alsactl(1)
ConditionPathExists=!/etc/alsa/state-daemon.conf
ConditionPathExistsGlob=/dev/snd/control*
After=alsa-state.service

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=-/usr/sbin/alsactl -E HOME=/run/alsa restore
ExecStop=-/usr/sbin/alsactl -E HOME=/run/alsa store

You need to change the latter two lines. So edit the service file to override these lines:

$ sudo systemctl edit alsa-restore.service

Then add the following lines containing the filename of the Seeed driver's asound state file:

[Service]
ExecStart=
ExecStart=-/usr/sbin/alsactl -E HOME=/run/alsa -f /etc/voicecard/wm8960_asound.state restore
ExecStop=
ExecStop=-/usr/sbin/alsactl -E HOME=/run/alsa -f /etc/voicecard/wm8960_asound.state store

The empty ExecStart and ExecStop commands are needed because you want to replace the original commands instead of adding extra commands.

Reload the systemd configuration after your changes:

$ sudo systemctl daemon-reload

Then reboot. After this, every change you make to the ALSA mixer (for instance with the alsamixer command) will be saved when your Raspberry Pi shuts down and reloaded when it boots, so it always uses the volume you have set.