Implementing an analog-to-Airplay bridge
Implementing an analog-to-Airplay bridge
Many modern speakers and multi-room audio systems support streaming
services and network playback, but no longer provide analog inputs.
This makes it difficult to use classic audio equipment.
Typical examples include cassette decks, turntables with external
preamps, FM tuners, and other legacy audio sources that cannot be
connected directly to modern AirPlay speakers.
With a HiFiBerry ADC and a Raspberry Pi, these analog sources can be
digitized and streamed to AirPlay-enabled speakers. This allows you
to integrate classic audio equipment into a modern, wireless audio
setup.
While digitizing cassette tapes or vinyl records is an obvious use
case, live streaming analog sources to smart speakers opens up many
additional possibilities.
This guide shows one possible implementation using a Raspberry Pi
and a HiFiBerry ADC.
Please note: this guide is provided as is. Individual support
is not included. Feel free to post questions
in our community area.
What do you need?
- A Raspberry Pi. Older models will work, but we recommend at least a
Raspberry Pi 3. This is the first model supporting the modern ARM64
architecture. - A HiFiBerry ADC:
- DAC+ ADC (no input gain control)
- DAC2 ADC Pro (flexible input gain control)
- Studio ADC (for balanced input sources)
- Raspberry Pi OS (64-bit)
- PipeWire (standard audio middleware on Debian Trixie)
Setting up the base system
- Install Raspberry Pi OS 64-bit. The Lite version is sufficient. If
you use the Lite image, install the following packages:- pipewire
- pipewire-alsa (optional but recommended)
- wireplumber
- Reboot and verify that PipeWire and WirePlumber are running in user
context:
systemctl --user status pipewire \ wireplumber
Configuring PipeWire
In this section we enable the RAOP sink. RAOP is the protocol used by
AirPlay. It allows PipeWire to automatically discover compatible
speakers in your local network.
- Enable the RAOP sink (AirPlay protocol)
AirPlay devices use their own clock, which is not synchronized with
the Raspberry Pi audio clock. Therefore resampling is required when
forwarding audio from the ADC to an AirPlay device.
Create the configuration directory:
mkdir -p ~/.config/pipewire/pipewire.conf.d
Create the file
~/.config/pipewire/pipewire.conf.d/raop.conf
with the following contents:
context.properties = {
default.clock.allowed-rates = [
44100
48000
96000
]
}
context.modules = [
{
name = libpipewire-module-raop-discover
args = {
raop.audio.codec = "PCM"
raop.latency.ms = 500
}
}
]
Restart PipeWire. AirPlay devices on your network will be detected
automatically:
pw-cli ls | grep raop | \ grep "node.name"
node.name = \ "raop_sink.sonyaudio.local.10.10.11.227.7000" node.name = \ "raop_sink.hifiberry.local.10.10.11.109.7000"
Routing ADC input to the AirPlay device
First, determine the exact node name of your AirPlay device. The name
includes the IP address. It is strongly recommended to assign a
static IP address to the AirPlay speaker.
While this routing could theoretically be handled by WirePlumber
rules, documentation for version 0.5 is still limited. For
simplicity, we use pw-link together with a systemd user
service.
Create the file
:
~/.config/systemd/user/adc-to-raop.service
[Unit]
Description=Auto-link ADC to Sony RAOP
After=pipewire.service wireplumber.service
Requires=pipewire.service wireplumber.service
[Service]
Type=oneshot
Restart=on-failure
RestartSec=10
ExecStartPre=/usr/bin/sleep 5
ExecStart=/usr/bin/bash -c "\
/usr/bin/pw-link \
alsa_input.platform-soc_sound.stereo-fallback:\
capture_FL \
raop_sink.sonyaudio.local.10.10.11.227.7000:\
send_FL; \
/usr/bin/pw-link \
alsa_input.platform-soc_sound.stereo-fallback:\
capture_FR \
raop_sink.sonyaudio.local.10.10.11.227.7000:\
send_FR"
RemainAfterExit=yes
[Install]
WantedBy=default.target
Reload systemd and enable the service:
systemctl --user daemon-reload systemctl --user enable adc-to-raop.service systemctl --user start adc-to-raop.service
Verify the links using:
pw-link -l
Audio from the analog input should now be streamed to the AirPlay
speaker.
Bonus: Force high sample rate on the input
By default, PipeWire may open the ADC at 44.1 kHz because this is the
native AirPlay rate. If you also want to record audio locally, this
is not ideal.
Because the first connection determines the sample rate, PipeWire
would otherwise resample internally. To avoid this, we force the ADC
node to use a higher sample rate via WirePlumber.
Create the file
:
~/.config/wireplumber/wireplumber.conf.d/96k.conf
monitor.alsa.rules = [
{
matches = [
{
node.name =
"alsa_input.platform-soc_sound.stereo-fallback"
}
]
actions = {
update-props = {
audio.rate = 96000
node.force-rate = 96000
}
}
}
]
To verify sample rates and processing load, use:
pw-top