Almost 4 years ago I bought the respeaker4 mic array<https://wiki.seeedstudio.com/ReSpeaker_4_Mic_Array_for_Raspberry_Pi/> for building my personal voice assistant.
That project never really manifested because setting up such a system was just not easy enough. However times have changed and with rhasspy<https://rhasspy.readthedocs.io/> it seems like a lot of painpoints are solved, at least in the Voice Assistant department. Machine-learning models do the heavy lifting to create text from speech, there is a working wakeword detection and rhasspy is even training these ML models to better extract the intent from your command.
I want all that on my Raspberry Pi 4 running NixOS<https://nixos.org/>.
With a "well supported" microphone array i thought the hardware is no problem at all, however it turns out the respeaker requires some extra tweaking to get it actually running on NixOS. On a "standard" raspbian with a raspberrypi 3b these issues might not have occurred.
I write about two nix-related topics:
- The configuration to set up the respeaker kernel module and Device Tree overlay
- How to package seeed-voicecard, an out-of-tree kernel module for NixOS
This article assumes existing understanding of NixOS as a concept, the Nix Language and how configuration and software is manged by the nix package manager. It will not be helpful anyone ho wants to learn about the concepts of the nix ecosystem.
Configure Respeaker kernel module
This is the configuration i ended up with down below i go through the important lines.
{ config, lib, pkgs, ... }:
let
seeed-voicecard = (pkgs.callPackage seeed-voicecard.nix { kernel = config.boot.kernelPackages.kernel; }); # [1]
in
{
imports = [ <nixos-hardware> ]; # [1]
hardware.raspberry-pi."4".i2c1.enable = true; # [2]
environment.systemPackages = [ pkgs.i2c-tools ];
hardware.raspberry-pi."4".audio.enable = true; # [3]
hardware.raspberry-pi."4".apply-overlays-dtmerge.enable = true; # [4]
boot.extraModulePackages = [ seeed-voicecard ]; # [5]
boot.initrd.kernelModules = [
"snd-soc-seeed-voicecard"
"snd-soc-ac108"
"i2c-dev" # [6]
];
sound.enable = true; # [7]
boot.loader.raspberryPi.firmwareConfig = [ # [8]
"dtparam=i2c_arm=on"
"dtparam=i2s=on"
"dtparam=spi=on"
];
hardware.deviceTree = {
enable = true; # [9]
overlays = [
{ name = "respeaker-4mic"; dtsFile = "${seeed-voicecard}/lib/dts/seeed-4mic-voicecard-overlay.dts";}
];
};
}
Package seeed-voicecard
The NixOS wiki provides an article about how packaging a kernel module looks like, but as always there are some caveats that may need some explanation.
To package the seed-voicecard i built upon the bkchr configuration on github<https://github.com/bkchr/nixos-config/blob/master/babyphone.nix>, thanks for this!
{ pkgs, lib, fetchFromGitHub, fetchpatch
,kernel # [1]
, ... }:
pkgs.stdenv.mkDerivation rec {
name = "seeed-voicecard-${version}-module-${kernel.modDirVersion}";
version = "v4.1-post";
src = fetchFromGitHub { # [2]
owner = "respeaker";
repo = "seeed-voicecard";
rev = "c52606626de050bdad85803d7e427a64cb0cf05c";
hash = "sha256-sFReX9Nz9TDRvheKfPijRw1wQ++jJUk5+lOwVmfx3wA=";
};
KERNELDIR = "${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"; # [3]
NIX_CFLAGS = ["-Wno-error=cpp"];
patches = [ # [4]
(fetchpatch { url = "https://patch-diff.githubusercontent.com/raw/respeaker/seeed-voicecard/pull/323.patch";
hash = "sha256-coa0ZXDAGYxxi4ShL1HpOebfwOSmIpfdbEIYZtBWlYI="; })
];
nativeBuildInputs = [ pkgs.perl ] ++ kernel.moduleBuildDependencies;
buildInputs = [ pkgs.alsa-lib ]; # [5]
buildPhase = ''
make -C $KERNELDIR M=$(pwd) modules
make -C ac108_plugin libasound_module_pcm_ac108.so # [7]
sed -i "s/brcm,bcm2708/raspberrypi/" *.dts # [8]
'';
installPhase = ''
mkdir -p $out/lib/modules/${kernel.modDirVersion}/sound/soc/codecs
mkdir -p $out/lib/modules/${kernel.modDirVersion}/sound/soc/bcm
cp snd-soc-wm8960.ko $out/lib/modules/${kernel.modDirVersion}/sound/soc/codecs
cp snd-soc-ac108.ko $out/lib/modules/${kernel.modDirVersion}/sound/soc/codecs
cp snd-soc-seeed-voicecard.ko $out/lib/modules/${kernel.modDirVersion}/sound/soc/bcm
mkdir $out/lib/dts $out/lib/alsa-lib
cp *.dts $out/lib/dts # [9]
cp ac108_plugin/libasound_module_pcm_ac108.so $out/lib/alsa-lib
'';
}
Comments