Skip to content

Making an Analog In to Airplay RPi Transmitter

Jack Klink edited this page Mar 9, 2023 · 11 revisions

Say you have a record player in one room and some AirPlay speakers scattered about? Ever want to play from the analog out to the AirPlay speakers? Here's a guide on doing that with a Raspberry Pi. This is mostly a writeup of Issue #632; and will walk through from ground up with a blank RPi.

Get RPi Image

Go fetch the lastest Raspbian. Go with the lite version (you won't need a gui desktop or any other fancy software if it's a headless server). Burn the image to your SD card.

Set up for headless In the SD card's /boot mount.

  1. Make a blank file called ssh.
  2. Make a file called wpa_supplicant.conf and fill in your network information in this template.
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US 
network={
    ssid="MyWifi"
    psk="MyWifiPassword"
    scan_ssid=1
}

Setup the RPi

Power up the pi! It should jump on your Wifi at first boot. You still have a few things to do. If you don't have a monitor or keyboard hooked up, you can just SSH into it if you know the IP. Username is pi password is raspberry.

  1. Run passwd and update the password.
  2. Run sudo raspi-config and update the tool.
  3. Still in the raspi-config tool set your language, local, time, etc. Also Expand the File System while you are in there.
  4. Reboot.

Update things

Log back in run:

  1. sudo apt-get update
  2. sudo apt-get upgrade
  3. sudo apt-get install git libasound2-dev
  4. sudo apt-get install tmux mosh emacs htop glances

That last install step is optional but things I can't live without.

Install OwnTone

First, just follow these instructions.

In the /etc/owntone.conf file, hunt and peck and set the following. I'm adding "10.0" to the trusted networks as that's my network prefix. Set whatever password you like and you can change that music dir if you want, just remember it as you'll need it later:

admin_password = ""
trusted_networks = { "localhost", "192.168", "10.0", "fd" }
directories = { "/home/pi/music" }

Test owntone

At this point, it should all be running. Restart the server:

sudo service owntone restart

Upload an MP3 to /home/pi/music: wget https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_5MG.mp3 In your webbrowser, go to OwnTone's web UI (typically http://owntone.local:3689/), and set it up, play the MP3 to the remote speakers. It is very important that everything is working at this point...nothing will work from here out if not.

Test Configure the Raw Audio In

  1. Make a fifo file: mkfifo -m 666 /home/pi/music/AUX
  2. Run arecord -L and pick your soundcard. Mine is hw:CARD=sndrpihifiberry,DEV=0
  3. Pipe the soundcard to the fifo file: arecord -D hw:CARD=sndrpihifiberry,DEV=0 -f cd -d 0 -t raw > /home/pi/music/AUX
  4. Login to the server: http://owntone.local:3689
  5. You should see a "music file" called AUX. Play it, it should be the pass through from your audio device (receiver, record player, cd player, whatever).
  6. All good? Great, stop the arecord program.

PS: If you're using a HiFiBerry DAC+ADC, there's an important note on this page.

CPIPED

So the arecord is cool...cpiped wraps it nicely with some extra pizzaz like signaling the AUX queue start and stop.

Make it

  1. cd ~/
  2. mkdir bin/
  3. git clone "https://github.com/b-fitzpatrick/cpiped.git"
  4. cd cpiped/
  5. make cpiped
  6. cp cpiped ~/bin

Config it

The sound detect script uses a secondary FIFO file called .audioDetectPipe as an intermediary for the sound output (see the cat line below). We need to create this FIFO file too, or cpiped will not work:

mkfifo -m 666 /home/pi/.audioDetectPipe

Make a file at ~/bin/soundDetect.sh:

#!/bin/bash
cat /home/pi/.audioDetectPipe > /home/pi/music/AUX &
echo $! > /tmp/catPipe.pid

Make a file at ~/bin/soundAbsence.sh:

#!/bin/bash
kill $(< /tmp/catPipe.pid)
echo " " > /tmp/catPipe.pid

Now make them executable:

cd ~/bin
chmod +x *.sh

Turn on services at boot time

What's my sound card again?

Run arecord -l and you'll see something like:

**** List of CAPTURE Hardware Devices ****
card 0: sndrpihifiberry [snd_rpi_hifiberry_dacplusadcpro], device 0: HiFiBerry DAC+ADC PRO HiFi multicodec-0 [HiFiBerry DAC+ADC PRO HiFi multicodec-0]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

This lists all the audio cards. For us, we want the first one which would be hw:0,0. Remember that. It's a different name than the last time when we tested it.

Next, make a file at /lib/systemd/system/cpiped.service and sub in your device if it's not -d "hw:0,0":

[Unit]
Description=cpiped
After=sound.target

[Service]
Type=forking
KillMode=none
User=pi
ExecStart=/home/pi/bin/cpiped -d "hw:0,0" -s /home/pi/bin/soundDetect.sh -e /home/pi/bin/soundAbsence.sh -t 800 -D /home/pi/.audioDetectPipe
ExecStop=/usr/bin/killall -9 cpiped
WorkingDirectory=/home/pi

[Install]
WantedBy=multi-user.target

To change the silence threshold for audio detection, you can change -t 800 to another number. cpiped has a sound range of 1 to 32767. The default is 100 which is often too low for analog audio situations like a turntable.

Then run:

  1. sudo systemctl enable owntone
  2. sudo systemctl enable cpiped

Enjoy!

So the music should stream through now. The cpiped tool will automatically open and close the stream if audio is present. You can dive in and edit the /etc/owntone.conf file if you want to set up default speakers and run alsamixer to set the input gain.

Notes for HiFiBerry DAC+ADC Pro

You can turn off the board LEDs if you want. I never got the board to work outside of slave mode.

  1. In /boot/config.txt
  2. Add: dtoverlay=hifiberry-dacplusadcpro,slave,leds_off=true
  3. Remove: dtparam=audio=on
  4. Run: sudo rpi-update